diff --git a/.gitattributes b/.gitattributes index 4f81d1136a..a1202033e2 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 UnitTests/__Snapshots__/** filter=lfs diff=lfs merge=lfs -text -PreviewTests/__Snapshots__/** filter=lfs diff=lfs merge=lfs -text \ No newline at end of file +PreviewTests/Sources/__Snapshots__/** filter=lfs diff=lfs merge=lfs -text \ No newline at end of file diff --git a/.githooks/post-checkout b/.githooks/post-checkout index 5765f32c0c..ca7fcb4008 100755 --- a/.githooks/post-checkout +++ b/.githooks/post-checkout @@ -1,9 +1,3 @@ #!/bin/sh -command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting '.git/hooks/post-checkout'.\n"; exit 2; } +command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting the 'post-checkout' file in the hooks directory (set by 'core.hookspath'; usually '.git/hooks').\n"; exit 2; } git lfs post-checkout "$@" - -#!/bin/bash -export PATH="$PATH:/opt/homebrew/bin" - -# ignores updates of 'secrets.xcconfig' to avoid pushing sensitive data by mistake -git update-index --assume-unchanged ElementX/SupportingFiles/secrets.xcconfig \ No newline at end of file diff --git a/.githooks/post-commit b/.githooks/post-commit index e5230c305f..52b339cb3f 100755 --- a/.githooks/post-commit +++ b/.githooks/post-commit @@ -1,3 +1,3 @@ #!/bin/sh -command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting '.git/hooks/post-commit'.\n"; exit 2; } +command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting the 'post-commit' file in the hooks directory (set by 'core.hookspath'; usually '.git/hooks').\n"; exit 2; } git lfs post-commit "$@" diff --git a/.githooks/post-merge b/.githooks/post-merge index c99b752a52..a912e667aa 100755 --- a/.githooks/post-merge +++ b/.githooks/post-merge @@ -1,3 +1,3 @@ #!/bin/sh -command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting '.git/hooks/post-merge'.\n"; exit 2; } +command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting the 'post-merge' file in the hooks directory (set by 'core.hookspath'; usually '.git/hooks').\n"; exit 2; } git lfs post-merge "$@" diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 60c0f533e1..6606b91cf2 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -68,7 +68,7 @@ body: attributes: label: Will you send logs? description: | - Did you know that you can shake your phone to submit logs for this issue? Trigger the defect, then shake your phone and you will see a popup asking if you would like to open the bug report screen. Click YES, and describe the issue, mentioning that you have also filed a bug (it's helpful if you can include a link to the bug). Send the report to submit anonymous logs to the developers. + You can submit logs for this issue from the login screen or the application settings by chosing `Report a problem`. Describe the issue, mentioning that you have also filed a bug (it's helpful if you can include a link to the bug). Send the report to submit anonymous logs to the developers. options: - 'Yes' - 'No' diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index a06b8e5d09..7b0eb99c0b 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -59,23 +59,6 @@ jobs: path: ~/Library/Logs/scan/IntegrationTests-IntegrationTests.log retention-days: 2 if-no-files-found: ignore - - - name: Checkout gh-pages branch (for perf stats) - if: always() - uses: actions/checkout@v4 - with: - ref: gh-pages - path: gh-pages - - - name: Post-process archive to obtain performance metrics and upload to gh-pages - if: always() - run: | - ./Tools/Scripts/parsePerformanceMetrics.sh ~/Library/Logs/scan/IntegrationTests-IntegrationTests.log $GITHUB_SHA | tee perf-results.csv - cat perf-results.csv >> $GITHUB_WORKSPACE/gh-pages/performance/perf-data.csv - cd $GITHUB_WORKSPACE/gh-pages/performance/ - git add . - git commit -m "Results for $GITHUB_SHA" - git push - name: Collect coverage run: xcresultparser -q -o cobertura -t ElementX -p $(pwd) fastlane/test_output/IntegrationTests.xcresult > fastlane/test_output/integration-cobertura.xml @@ -87,3 +70,15 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} flags: integrationtests + - name: Collect test results + if: ${{ !cancelled() }} + run: xcresultparser -q -o junit -p $(pwd) fastlane/test_output/IntegrationTests.xcresult > fastlane/test_output/integration-junit.xml + + - name: Upload test results to Codecov + if: ${{ !cancelled() }} + uses: codecov/test-results-action@v1 + continue-on-error: true + with: + fail_ci_if_error: false + token: ${{ secrets.CODECOV_TOKEN }} + flags: integrationtests diff --git a/.github/workflows/translations-pr.yml b/.github/workflows/translations-pr.yml index 77b52da476..2c4ca11abb 100644 --- a/.github/workflows/translations-pr.yml +++ b/.github/workflows/translations-pr.yml @@ -28,7 +28,7 @@ jobs: run: swift run tools generate-sas - name: Create PR for Translations - uses: peter-evans/create-pull-request@v6 + uses: peter-evans/create-pull-request@v7 with: token: ${{ secrets.ELEMENT_BOT_TOKEN }} commit-message: Translations update diff --git a/.github/workflows/ui_tests.yml b/.github/workflows/ui_tests.yml index ac3546a400..eab569396a 100644 --- a/.github/workflows/ui_tests.yml +++ b/.github/workflows/ui_tests.yml @@ -30,6 +30,9 @@ jobs: restore-keys: | ${{ runner.os }}-gems- + - name: Free disk space + run: ci_scripts/free_space.sh + - name: Setup environment run: source ci_scripts/ci_common.sh && setup_github_actions_environment @@ -64,4 +67,16 @@ jobs: fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} flags: uitests - + + - name: Collect test results + if: ${{ !cancelled() }} + run: xcresultparser -q -o junit -p $(pwd) fastlane/test_output/UITests.xcresult > fastlane/test_output/ui-junit.xml + + - name: Upload test results to Codecov + if: ${{ !cancelled() }} + uses: codecov/test-results-action@v1 + continue-on-error: true + with: + fail_ci_if_error: false + token: ${{ secrets.CODECOV_TOKEN }} + flags: uitests diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 32120d0d3a..63fa5e54ed 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -65,3 +65,18 @@ jobs: fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} flags: unittests + + - name: Collect test results + if: ${{ !cancelled() }} + run: | + xcresultparser -q -o junit -p $(pwd) fastlane/test_output/UnitTests.xcresult > fastlane/test_output/unit-junit.xml + xcresultparser -q -o junit -p $(pwd) fastlane/test_output/PreviewTests.xcresult > fastlane/test_output/preview-junit.xml + + - name: Upload test results to Codecov + if: ${{ !cancelled() }} + uses: codecov/test-results-action@v1 + continue-on-error: true + with: + fail_ci_if_error: false + token: ${{ secrets.CODECOV_TOKEN }} + flags: unittests diff --git a/.swiftlint.yml b/.swiftlint.yml index 10fc52d3c0..d8c789ffa0 100755 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -60,6 +60,12 @@ custom_rules: message: "Please use explicit spacing in HStacks." severity: warning + compound_color_conversion: + regex: "UIColor\\(\\.compound" + match_kinds: identifier + message: "Please use the UIColor token directly to ensure the colour scheme is honoured." + severity: warning + print_deprecation: regex: "\\b(print)\\b" match_kinds: identifier diff --git a/CHANGES.md b/CHANGES.md index 6b55b72abd..8ae2d2c28c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,236 @@ +## Changes in 1.8.3 (2024-09-19) + +### What's Changed + +โœจ Features +* crypto: Add configuration flag to enable invisible crypto by @BillCarsonFr in https://github.com/element-hq/element-x-ios/pull/3247 +* quick and dirty /join command by @ara4n in https://github.com/element-hq/element-x-ios/pull/3288 + +๐Ÿ› Bugfixes +* Await for room sync only for push notification invites by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3307 + +๐Ÿงฑ Build +* Try to stop random codecov test result action failures from failing the whole test run. by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3301 + +Others +* Various Danger fixes by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3304 + + +**Full Changelog**: https://github.com/element-hq/element-x-ios/compare/1.8.2...1.8.3 + +## Changes in 1.8.2 (2024-09-18) + +### What's Changed + +โœจ Features +* Allow registration on matrix.org using a custom helper URL. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3282 + +๐Ÿ™Œ Improvements +* Allow account deactivation when not using OIDC. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3295 + +๐Ÿ—ฃ Translations +* Translations update by @RiotRobot in https://github.com/element-hq/element-x-ios/pull/3283 + +๐Ÿงฑ Build +* Bump SDK to 1.0.51 by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3298 + +๐Ÿšง In development ๐Ÿšง +* Add a WebRegistrationScreen (not included in the flow yet). by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3281 +* Added analytics for message pinning by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3284 + +Others +* Bump the RustSDK to v1.0.50 by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3292 +* Push the deactivate account screen. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3297 +* Use the new strings for send failures when the unsigned devices are your own. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3299 +* Stop delaying subscriptions until after startup by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3294 + + +**Full Changelog**: https://github.com/element-hq/element-x-ios/compare/1.8.1...1.8.2 + +## Changes in 1.8.1 (2024-09-13) + +### What's Changed + +๐Ÿ› Bugfixes +* Make sure we don't reuse an old NSEUserSession after logging out and back in. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3273 +* Make sure we reset the feature flag when upgrading to SSS. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3272 +* Fix interactive dismissal of our QLPreviewController iOS 18 (when built with Xcode 16). by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3274 +* Replace client side room awaiting with the SDKs new `awaitRoomRemoteEcho` method by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3279 +* Handle notifications properly when a call is happening. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3276 + +๐Ÿงฑ Build +* Upload test results to Codecov. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3266 + + +**Full Changelog**: https://github.com/element-hq/element-x-ios/compare/1.8.0...1.8.1 + +## Changes in 1.8.0 (2024-09-11) + +### What's Changed + +โœจ Features +* Add a banner that offers the user to transition to native sliding sync by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3252 + +๐Ÿ™Œ Improvements +* Delay setting up subscriptions until the RoomListService is running in order to avoid cancelling in flight initial sync requests by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3233 +* Require acknowledgement to send to verified users who have unsigned devices or have changed their identity. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3215 +* Make the SessionDirectories type responsible for cleaning up data. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3261 + +๐Ÿ› Bugfixes +* Rewrite how out of band verification changes are handled within the onboarding flows by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3234 +* Allow voice message playback in the background by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3236 +* Fix wrong durations for uploaded media by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3245 +* Make sure introspections are used on iOS 18. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3248 +* Bring back default controls for QuickLook based media viewers by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3254 +* Reduce the maximum height used by the plain text composer by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3255 +* Force frame sizes for timeline items that are missing sizing info by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3259 + +๐Ÿ—ฃ Translations +* Translations update by @RiotRobot in https://github.com/element-hq/element-x-ios/pull/3239 + +๐Ÿงฑ Build +* Replace Prefire with a very similar but simpler and more direct approach by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3232 +* Switch codecov-action back to v3 as 4 significantly decreases coverage by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3246 +* Free up CI runner disk space before running UI tests. by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3253 +* version bump to 1.8.0 by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3260 +* Sdk v1.0.47 by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3265 + +๐Ÿšง In development ๐Ÿšง +* Pin Tweaks by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3242 +* Allow redacted messages to be viewed and unpinned by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3251 +* Added a pin icon by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3257 + +Others +* Switch license to AGPL by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3237 +* Remove SS proxy migration and waitlist screens by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3154 +* Update bug.yml by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3250 + + +**Full Changelog**: https://github.com/element-hq/element-x-ios/compare/1.7.5...1.8.0 + +## Changes in 1.7.5 (2024-09-04) + +### What's Changed + +โœจ Features +* Add a logout button on the identity confirmation screen by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3212 + +๐Ÿ› Bugfixes +* Make sure reactions always go through the timeline controller. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3209 +* Prevent issues when loading user profiles by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3213 +* Accept current autocorrection/suggestion before sending a message by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3219 +* Update subscriptions if visible range rooms change without the range itself changing by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3220 +* Prevent verification state changes other than `verified` from blocking the user on the session verification screen by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3224 +* Make pinned events required state in SlidingSync by @jmartinesp in https://github.com/element-hq/element-x-ios/pull/3225 +* Force room title headers to layout on one single line by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3229 + +๐Ÿ—ฃ Translations +* Translations update by @RiotRobot in https://github.com/element-hq/element-x-ios/pull/3218 + +๐Ÿšง In development ๐Ÿšง +* Native Sliding Sync Discovery by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3211 + +Others +* Update GitHub Actions (major) by @renovate in https://github.com/element-hq/element-x-ios/pull/3222 +* Update GitHub Actions (major) by @renovate in https://github.com/element-hq/element-x-ios/pull/3227 +* Bump the RustSDK to v1.0.44 by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3230 + +### New Contributors +* @jmartinesp made their first contribution in https://github.com/element-hq/element-x-ios/pull/3225 + +**Full Changelog**: https://github.com/element-hq/element-x-ios/compare/1.7.4...1.7.5 + +## Changes in 1.7.4 (2024-08-27) + +### What's Changed + +โœจ Features +* Show encryption authenticity warnings on messages in the timeline. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3180 +* Picture in Picture support for Calls (requires a supported widget deployment). by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3204 + +๐Ÿ™Œ Improvements +* Clarify the copy for Mentions in notifications. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3142 +* Remove a notification if its event has been redacted. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3191 + +๐Ÿ› Bugfixes +* RoomScreenViewModel refactor part 2 by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3169 +* Automatically try reloading failed images on network changes by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3170 +* Fixes problems processing invites, build rooms differently based on their membership by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3189 + +โš ๏ธ API Changes +* Introduce a new `RoomProxyType` and treat rooms differently based on their membership state by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3187 + +๐Ÿ—ฃ Translations +* Translations update by @RiotRobot in https://github.com/element-hq/element-x-ios/pull/3172 +* Translations update by @RiotRobot in https://github.com/element-hq/element-x-ios/pull/3179 +* Translations update by @RiotRobot in https://github.com/element-hq/element-x-ios/pull/3201 + +๐Ÿšง In development ๐Ÿšง +* RoomScreenViewModel is now TimelineViewModel by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3157 +* PinnedBanner is now managed by the RoomScreenViewModel by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3163 +* Navigation support for upcoming Element Call Picture in Picture mode. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3174 +* Use native video call picture in picture! by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3190 +* Pinned Events Timeline actions and differentiation by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3182 +* `TimelineKind` refactor by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3193 + +Others +* Add a danger check for PR titles that contain a "Fixes #1234" prefix. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3161 +* Update package acknowledgements (after resetting the packages). by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3167 +* Bump the SDK to v1.0.39 by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3171 +* Remove GenericCallLinkCoordinator, merging it into CallScreen. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3181 +* Fix the call URL input field in Developer Options by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3192 +* Update the SDK by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3196 +* Update the client's request timeout to match the SDK's default. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3205 + + +**Full Changelog**: https://github.com/element-hq/element-x-ios/compare/1.7.3...1.7.4 + +## Changes in 1.7.3 (2024-08-13) + +### What's Changed + +โœจ Features +* Crypto identity reset by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3107 +* Fixes #3050 - Sync mute state between ElementCall and CallKit by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3120 + +๐Ÿ› Bugfixes +* Fix a bug where a new line in the composer could move the caret. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3114 +* Make sure the whole room header is tappable. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3125 +* Force the room list search text field to always be displayed by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3127 +* Fix search in the Change Roles screen. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3138 +* Various ElementCall fixes by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3140 +* Fixes #3126 - Prevent identity confirmation from blocking the user's progress after registering through OIDC by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3141 +* Fix a bug where the server versions for matrix.org were used when signing in to a different server. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3155 +* Stop showing filters when the room list is not in the `rooms` display mode by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3156 + +๐Ÿงฑ Build +* Update sonarcloud project key by @guillaumevillemont in https://github.com/element-hq/element-x-ios/pull/3112 +* Use SwiftPackageList to generate acknowledgements. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3117 + +๐Ÿšง In development ๐Ÿšง +* Show Encryption Authenticity warnings on messages in the timeline. by @BillCarsonFr in https://github.com/element-hq/element-x-ios/pull/3051 +* Pinned items timeline implementation for the banner by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3099 +* Add Encryption Authenticity explanations. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3116 +* Pinned events banner loading state by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3118 +* Finalise strings/icons for EncryptionAuthenticity. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3121 +* state events for pinning and unpinning by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3123 +* Pinned events banner goes backwards by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3128 +* Navigate to the Pinned events timeline by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3139 +* Fix for a memory leak by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3143 +* Remove links from pinned events banner by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3153 + +Others +* Put a space between the version and build numbers on the Nightly icon by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3124 +* Force update the home screen every time the room list changes by manually moving the inner scrollview by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3122 +* Delete more unnecessary logs by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3129 +* Adopt APIs available in SDK version 1.0.36 by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3145 +* Bump the SDK to v1.0.37 by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3158 + +### New Contributors +* @guillaumevillemont made their first contribution in https://github.com/element-hq/element-x-ios/pull/3112 + +**Full Changelog**: https://github.com/element-hq/element-x-ios/compare/1.7.2...1.7.3 + ## Changes in 1.7.2 (2024-07-30) ### What's Changed diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4af74e5a11..192ad3b160 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -45,10 +45,10 @@ swift run tools build-sdk --help ### Tools -The project depends on some tools for the build process. These are all included in the `Brewfile` and can be easily installed by running +The project depends on some tools for the build process which are normally installed through `swift run tools setup-project`. Installing them manually though is as easy as copying what the [script does](https://github.com/element-hq/element-x-ios/blob/develop/Tools/Sources/SetupProject.swift) ``` -brew bundle +brew install [...] ``` Git LFS is used to store UI test snapshots. `swift run tools setup-project` will already install it, however it can also be installed after a checkout by running: @@ -112,4 +112,4 @@ We also gather coverage reports on every PR through [Codecov](https://app.codeco ## Thanks -Thank your for contributing to Matrix projects! \ No newline at end of file +Thank your for contributing to Matrix projects! diff --git a/Dangerfile.swift b/Dangerfile.swift index 43508205ea..32f1ddca30 100644 --- a/Dangerfile.swift +++ b/Dangerfile.swift @@ -1,7 +1,13 @@ import Danger import Foundation -SwiftLint.lint(inline: true) +SwiftLint.lint(.modifiedAndCreatedFiles(directory: nil), + inline: true, + configFile: nil, + strict: false, + quiet: true, + swiftlintPath: nil, + markdownAction: { _ in }) let danger = Danger() @@ -34,21 +40,10 @@ if let ticketNumberRegex = try? NSRegularExpression(pattern: "#\\d+") { let signOff = "Signed-off-by:" let allowList = ["stefanceriu", - "Johennes", - "yostyle", - "SBiOSoftWhare", - "ismailgulek", - "Anderas", "pixlwave", "langleyd", "manuroe", - "gileluard", - "phlniji", - "aringenbach", - "flescio", - "Velin92", - "alfogrillo", - "nimau"] + "Velin92"] let requiresSignOff = !allowList.contains(where: { $0.caseInsensitiveCompare(danger.github.pullRequest.user.login) == .orderedSame @@ -80,7 +75,8 @@ if hasPngs { warn("You seem to have made changes to some resource images. Please consider using an SVG or PDF.") } -if danger.github.pullRequest.title.hasSuffix("โ€ฆ") { +let fixesRegex = try! Regex("(Fixes|Fix) #\\d+") +if danger.github.pullRequest.title.hasSuffix("โ€ฆ") || danger.github.pullRequest.title.starts(with: fixesRegex) { fail("Please provide a complete title that can be used as a changelog entry.") } diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..8d5496b220 --- /dev/null +++ b/ElementX.xcodeproj/project.pbxproj @@ -0,0 +1,8187 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + F8E276FD6DC43EADB85241BC /* Periphery */ = { + isa = PBXAggregateTarget; + buildConfigurationList = C0090A197E33AEC1E7CD03FD /* Build configuration list for PBXAggregateTarget "Periphery" */; + buildPhases = ( + 23C8392ACDCF25131DAF6F9B /* Scan */, + ); + dependencies = ( + ); + name = Periphery; + productName = Periphery; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 0033481EE363E4914295F188 /* LocalizationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C070FD43DC6BF4E50217965A /* LocalizationTests.swift */; }; + 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 */; }; + 020F7E70167FB2833266F2F0 /* AnalyticsSettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = D39D7F513A36C9C1951DB44C /* AnalyticsSettingsScreen.swift */; }; + 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 */; }; + 037006FB6DF1374F94E4058D /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFDCAC6CAAD65A2C24EA9C4B /* Dictionary.swift */; }; + 038AB2E86960FD240231D4C2 /* GeneratedPreviewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95A2E4BD7C0CAD25EF924A4C /* GeneratedPreviewTests.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 */; }; + 04A16B45228F7678A027C079 /* RoomHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 422724361B6555364C43281E /* RoomHeaderView.swift */; }; + 04F17DE71A50206336749BAC /* UserPreferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA241DEEF7C8A7181C0AEDC9 /* UserPreferenceTests.swift */; }; + 053B8BD2496207838878C6C9 /* PinnedItemsBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60C9BAE9F9436B14E4E22E8F /* PinnedItemsBannerView.swift */; }; + 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 */; }; + 066A1E9B94723EE9F3038044 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47EBB5D698CE9A25BB553A2D /* Strings.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 */; }; + 06F8EDF52E33A2D36BCC1161 /* AppLockScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56D6F88FE35A0979D2821E06 /* AppLockScreen.swift */; }; + 071A017E415AD378F2961B11 /* URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 227AC5D71A4CE43512062243 /* URL.swift */; }; + 07756D532EFE33DD1FA258E5 /* GeoURITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A7ED2EF5BDBAD2A7DBC4636 /* GeoURITests.swift */; }; + 077CB230153E072C94B1E6C3 /* AppAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D65BCC659FD9087E49B3C25 /* AppAppearance.swift */; }; + 07CC13C5729C24255348CBBD /* ElementCallWidgetDriver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 309AD8BAE6437C31BA7157BF /* ElementCallWidgetDriver.swift */; }; + 07F6382E29845D235BFA3308 /* DeactivateAccountScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE78CAD0B964C66FD06EF83E /* DeactivateAccountScreenModels.swift */; }; + 086D01E79C8E8D3F004FAF21 /* AudioPlayerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC9104846487244648D32C6D /* AudioPlayerProtocol.swift */; }; + 08CB4BD12CEEDE6AAE4A18DD /* WindowManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 035177BCD8E8308B098AC3C2 /* WindowManager.swift */; }; + 095C0ACFC234E0550A6404C5 /* AppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FC803282F9268D49F4ABF14 /* AppCoordinator.swift */; }; + 095D3906CF2F940C2D2D17CC /* RoomFlowCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FCB2126C091EEF2454B4D56 /* RoomFlowCoordinatorTests.swift */; }; + 09713669577CDA8D012EE380 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 6647C55D93508C7CE9D954A5 /* MatrixRustSDK */; }; + 09AAF04B27732046C755D914 /* SoftLogoutViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C5DAA1773F57653BF1C4F9 /* SoftLogoutViewModelTests.swift */; }; + 09C83DDDB07C28364F325209 /* MockRoomTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52D7074991B3267B26D89B22 /* MockRoomTimelineController.swift */; }; + 09D3D7D115318CAD131B4FE7 /* ResolveVerifiedUserSendFailureScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57084488B03BDB33C7B7CA0E /* ResolveVerifiedUserSendFailureScreenViewModelTests.swift */; }; + 0A0625A271EE5B06D2AAA069 /* HomeScreenSlidingSyncMigrationBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4691B8DE1D51DE152680098A /* HomeScreenSlidingSyncMigrationBanner.swift */; }; + 0A194F5E70B5A628C1BF4476 /* AdvancedSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4999B5FD50AED7CB0F590FF8 /* AdvancedSettingsScreenModels.swift */; }; + 0ACAA31FD0399CEEBA3ECC21 /* UserDetailsEditScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85149F56BA333619900E2410 /* UserDetailsEditScreenViewModelProtocol.swift */; }; + 0AE0AB1952F186EB86719B4F /* HomeScreenRoomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */; }; + 0BAF83521871E69D222EE8E4 /* ClientBuilderHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AC0CD1CAFD3F8B057F9AEA5 /* ClientBuilderHook.swift */; }; + 0BDA19079FD6E17C5AC62E22 /* RoomDetailsEditScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB06F22CFA34885B40976061 /* RoomDetailsEditScreen.swift */; }; + 0BE4D5CBF86956410F071F91 /* CreateRoomViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15A657D96779D1DEB8EF1327 /* CreateRoomViewModel.swift */; }; + 0BFA67AFD757EE2BA569836A /* ScrollViewAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53482ECA4B6633961EC224F5 /* ScrollViewAdapter.swift */; }; + 0C1E537A49ABB386F7554D4A /* HighlightedTimelineItemModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 59B7CC77B82C6C67DE3AD869 /* HighlightedTimelineItemModifier.swift */; }; + 0C346A4AD174F441EDB1414E /* IdentityConfirmationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB76A9AFC6CCAD4998D9B045 /* IdentityConfirmationScreenViewModel.swift */; }; + 0C47AE2CA7929CB3B0E2D793 /* ServerSelectionScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0685156EB62D7E243F097CFC /* ServerSelectionScreenViewModelProtocol.swift */; }; + 0C58A846F61949B1D545D661 /* NoticeRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 421E716C521F96D24ECE69B3 /* NoticeRoomTimelineItem.swift */; }; + 0C6DF318E9C8F6461E6ABDE7 /* EncryptionResetPasswordScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E1584F8BCF407BB94F48F04 /* EncryptionResetPasswordScreen.swift */; }; + 0C797CD650DFD2876BEC5173 /* CollapsibleReactionLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F7C6DDBB5D12F6EF6A3D6E1 /* CollapsibleReactionLayout.swift */; }; + 0C88044649BAEE6C49BFC43A /* SecureBackupControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C21A715237F2B6D6E80998C /* SecureBackupControllerProtocol.swift */; }; + 0C932A5158C1D0604DFC5750 /* ComposerToolbarViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA29952595B804DA221A0C1D /* ComposerToolbarViewModelTests.swift */; }; + 0CF81807BE5FBFC9E2BBCECF /* PollFormScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3368395F06AA180138E185B6 /* PollFormScreenUITests.swift */; }; + 0D4EB2ABAA5FE8CB10FDBCB8 /* TimelineItemFactoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AA3AF94A06D319BB37E52DA /* TimelineItemFactoryTests.swift */; }; + 0DC815CA24E1BD7F408F37D3 /* CollapsibleTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7C4EA55DA62F9D0F984A2AE /* CollapsibleTimelineItem.swift */; }; + 0E08BB72B2258652CF501A8B /* Version in Frameworks */ = {isa = PBXBuildFile; productRef = 2B9ACE4FCACB5A8812154424 /* Version */; }; + 0E3A2787C6AEC761A81A938A /* AuthenticationStartScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8609BE4CA71C30D1FCE3AF9B /* AuthenticationStartScreenModels.swift */; }; + 0E8C480700870BB34A2A360F /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = 4003BC24B24C9E63D3304177 /* DeviceKit */; }; + 0EA6537A07E2DC882AEA5962 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 187853A7E643995EE49FAD43 /* Localizable.stringsdict */; }; + 0EE5EBA18BA1FE10254BB489 /* UIFont+AttributedStringBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = E8CA187FE656EE5A3F6C7DE5 /* UIFont+AttributedStringBuilder.m */; }; + 0EEC614342F823E5BF966C2C /* AppLockTimerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A5B4CD611DE7E94F5BA87B2 /* AppLockTimerTests.swift */; }; + 0F6C8033FA60CFD36F7CA205 /* AppLockSetupPINScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A019A12C866D64CF072024B9 /* AppLockSetupPINScreenViewModel.swift */; }; + 108D3C0707A90B0F848CDBB9 /* ResolveVerifiedUserSendFailureScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60011EF0086E49DBD78E16E5 /* ResolveVerifiedUserSendFailureScreenModels.swift */; }; + 109AEB7D33C4497727AFB87F /* TimelineInteractionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BA894BC09972DC45E497D37 /* TimelineInteractionHandler.swift */; }; + 10D60D287025B71F4743A425 /* RoomDirectorySearchProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471BB7276C97AF60B3A5463B /* RoomDirectorySearchProxy.swift */; }; + 1146E9EDCF8344F7D6E0D553 /* MockCoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0376C429FAB1687C3D905F3E /* MockCoder.swift */; }; + 119AE9A3FC6E0606C1146528 /* NotificationSettingsEditScreenRoomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C97F8963B14EB0AF3940DDBF /* NotificationSettingsEditScreenRoomCell.swift */; }; + 11A6B8E3CBDBF0A4107FF4CE /* OnboardingFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3285BD95B564CA2A948E511 /* OnboardingFlowCoordinator.swift */; }; + 126EE01D8BEAEF26105D83C5 /* RoomDetailsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A5FEF17ED7E6176D922D4F /* RoomDetailsScreen.swift */; }; + 128FFD8A3D85845F9A927F47 /* PollRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF8548D48512127CCC17C520 /* PollRoomTimelineView.swift */; }; + 12C867E85E6D12EEDFD0B127 /* CustomStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C4762F8D6112E43117DB2F /* CustomStringConvertible.swift */; }; + 12CCA59536EDD99A3272CF77 /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC3F82523D6F48B926D6AF68 /* AppSettings.swift */; }; + 12CD8B5CC30A05061228BF9E /* TimelineItemMenuActionProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9E6065FC6BC4A1B4C629E08 /* TimelineItemMenuActionProvider.swift */; }; + 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 */; }; + 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 */; }; + 155063E980E763D4910EA3CF /* Analytics+SwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CFE236419E830E8946639C /* Analytics+SwiftUI.swift */; }; + 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 */; }; + 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 */; }; + 16E4F1B8B9BFE1367F96DDA7 /* CompletionSuggestionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 989FC684408B31A677F5538B /* CompletionSuggestionView.swift */; }; + 1702981A8085BE4FB0EC001B /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = D33116993D54FADC0C721C1F /* Application.swift */; }; + 172E6E9A612ADCF10A62CF13 /* BugReportServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A68BCE6438873D2661D93D0 /* BugReportServiceProtocol.swift */; }; + 1795EA6A6C4942CAE0459DF0 /* SecureBackupKeyBackupScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82B612853BFB68373249777B /* SecureBackupKeyBackupScreenViewModel.swift */; }; + 17BC15DA08A52587466698C5 /* RoomMessageEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80E815FF3CC5E5A355E3A25E /* RoomMessageEventStringBuilder.swift */; }; + 18867F4F1C8991EEC56EA932 /* UTType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 897DF5E9A70CE05A632FC8AF /* UTType.swift */; }; + 18E3786918486D4C9726BC84 /* FormButtonStyles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89FBFC09F9DAFF1E4BA97849 /* FormButtonStyles.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 */; }; + 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 */; }; + 1AB3D8563AB12635250A6A6E /* StaticLocationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C15E0017717EAE3A1D02D005 /* StaticLocationScreenCoordinator.swift */; }; + 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 */; }; + 1C409A26A99F0371C47AFA51 /* UserDiscoveryServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F615A00DB223FF3280204D2 /* UserDiscoveryServiceProtocol.swift */; }; + 1C815DD79B401DEBA2914773 /* TimelineItemMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4A1003A0F7A1DFB47F4E2D0 /* TimelineItemMock.swift */; }; + 1C8BC70A18060677E295A846 /* ShareToMapsAppActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4481799F455B3DA243BDA2AC /* ShareToMapsAppActivity.swift */; }; + 1C9BB74711E5F24C77B7FED0 /* RoomMembersListScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AEA0B743847CFA5B3C38EE4 /* RoomMembersListScreenCoordinator.swift */; }; + 1D5DC685CED904386C89B7DA /* NSRegularExpresion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95BAC0F6C9644336E9567EE6 /* NSRegularExpresion.swift */; }; + 1D623953F970D11F6F38499C /* AppLockService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851B95BB98649B8E773D6790 /* AppLockService.swift */; }; + 1D69E31913DF66426985909B /* EmojiPickerScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11151E78D6BB2B04A8FBD389 /* EmojiPickerScreenViewModelProtocol.swift */; }; + 1DC227816777A2F3A19657E5 /* RoomDirectorySearchScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCF71646898A2F720C5BFDF5 /* RoomDirectorySearchScreenViewModel.swift */; }; + 1E59B77A0B2CE83DCC1B203C /* LoginViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A05707BF550D770168A406DB /* LoginViewModelTests.swift */; }; + 1F3232BD368DF430AB433907 /* Compound in Frameworks */ = {isa = PBXBuildFile; productRef = 07FEEEDB11543A7DED420F04 /* Compound */; }; + 1FE593ECEC40A43789105D80 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */; }; + 1FEC0A4EC6E6DF693C16B32A /* StringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CEBCB9676FCD1D0F13188DD /* StringTests.swift */; }; + 206F0DBAB6AF042CA1FF2C0D /* SettingsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D487C1185D658F8B15B8F55 /* SettingsViewModelTests.swift */; }; + 208C19811613F9A10F8A7B75 /* MediaLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AFCE895ECFFA53FEE64D62B /* MediaLoader.swift */; }; + 20C16A3F718802B0E4A19C83 /* URLComponentsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76310030C831D4610A705603 /* URLComponentsTests.swift */; }; + 2118E35D312951B241067BD5 /* MessageComposerTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 345172AD4377E83A44BD864F /* MessageComposerTextField.swift */; }; + 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 */; }; + 2335D1AB954C151FD8779F45 /* RoomPermissionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0096BC5DA86AF6B6E5742AC /* RoomPermissionsTests.swift */; }; + 23701DE32ACD6FD40AA992C3 /* MediaUploadingPreprocessorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE203026B9AD3DB412439866 /* MediaUploadingPreprocessorTests.swift */; }; + 237FC70AA257B935F53316BA /* SessionVerificationControllerProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = C55D7E514F9DE4E3D72FDCAD /* SessionVerificationControllerProxy.swift */; }; + 238D561CA231339C6D4D06F3 /* ClientBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1C33355FFB0F0953C35036 /* ClientBuilder.swift */; }; + 241CDEFE23819867D9B39066 /* RoomChangePermissionsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE75941583A033A9EDC9FE0 /* RoomChangePermissionsScreenViewModel.swift */; }; + 244407B18B2F2D6466BA5961 /* RoomChangeRolesScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82DFA1B7B088D033E0794B82 /* RoomChangeRolesScreenCoordinator.swift */; }; + 244CB93DD7390379D905AFA8 /* DeactivateAccountScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E49D10BFA7E4D70A947888C /* DeactivateAccountScreen.swift */; }; + 24A1BBADAC43DC3F3A7347DA /* AnalyticsPromptScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E53BFB7E4F329621C844E8C3 /* AnalyticsPromptScreen.swift */; }; + 24A75F72EEB7561B82D726FD /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2141693488CE5446BB391964 /* Date.swift */; }; + 24B7CD41342C143117ADA768 /* Comparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B1CC9AA154F4D5435BF60A /* Comparable.swift */; }; + 24BDDD09A90B8BFE3793F3AA /* ClientProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6033779EB37259F27F938937 /* ClientProxyProtocol.swift */; }; + 24DF253C18D3E2C56DD0E597 /* TracingConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED003DF1B7CF40E7073A2280 /* TracingConfiguration.swift */; }; + 25618589E0DE0F1E95FC7B5C /* EmojiProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 099F2D36C141D845A445B1E6 /* EmojiProviderTests.swift */; }; + 256D76972BA3254F7CB7F88B /* LocationAnnotation.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAD8234D0E9C9B12BF9F240B /* LocationAnnotation.swift */; }; + 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 */; }; + 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 */; }; + 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 */; }; + 2835FD52F3F618D07F799B3D /* Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7310D8DFE01AF45F0689C3AA /* Publisher.swift */; }; + 290FDB0FFDC2F1DDF660343E /* TestMeasurementParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C4048041C1A6B20CB97FD18 /* TestMeasurementParser.swift */; }; + 292827744227DF61C930BDDB /* CreateRoomScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB0D6CB491777E7FC6B5BA12 /* CreateRoomScreen.swift */; }; + 29491EE7AE37E239E839C5A3 /* LocationSharingScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BEBF0E59F25E842EDB6FD11 /* LocationSharingScreenModels.swift */; }; + 2955F4C160CFD7794D819C64 /* EffectsScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 024F7398C5FC12586FB10E9D /* EffectsScene.swift */; }; + 298F9EC30E918F12AB7F1EE8 /* TypingIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81F0325E252B057FAEEE1B2D /* TypingIndicatorView.swift */; }; + 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 */; }; + 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 */; }; + 2BA59D0AEFB4B82A2EC2A326 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 50009897F60FAE7D63EF5E5B /* Kingfisher */; }; + 2BAA5B222856068158D0B3C6 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = B1E8B697DF78FE7F61FC6CA4 /* MatrixRustSDK */; }; + 2BBA132149DEBED6624084A8 /* MessageForwardingScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06FAE373A7F20780BA84B59C /* MessageForwardingScreenCoordinator.swift */; }; + 2BBC0EB1E07963810A5D7423 /* ReadMarkerRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A284622B32052015F1F89 /* ReadMarkerRoomTimelineView.swift */; }; + 2BBE320EE426A347AAE5C7DA /* IdentityConfirmationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00AFC5F08734C2EA4EE79C59 /* IdentityConfirmationScreen.swift */; }; + 2C4C750D0039AFABDF24236C /* TemplateScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 342BEBC3C5FC3F9943C41C4C /* TemplateScreenViewModelProtocol.swift */; }; + 2C5E832434EE94E21AB3B238 /* EmojiPickerScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EAE3E9D5EF4A6D5D9C6CFD /* EmojiPickerScreenViewModel.swift */; }; + 2CA61BB208CD82EBDB58CD13 /* VideoRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0CBEAB5F796BEFBAF7BB6A /* VideoRoomTimelineView.swift */; }; + 2CA6ABBC9A88EB89EA52FCCB /* ConfettiScene.scn in Resources */ = {isa = PBXBuildFile; fileRef = B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */; }; + 2D2D8A53B35BE8D8A01449C6 /* PinnedEventsBannerStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FA38E813BE14149F173F461 /* PinnedEventsBannerStateTests.swift */; }; + 2DA27D78560D5F79B917E163 /* AudioConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E44E35AA87F49503E7B3BF6E /* AudioConverter.swift */; }; + 2DD9D0FE7CB5CFC80D071451 /* AppLockScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C3E67E09FE5A35D73818C39 /* AppLockScreenModels.swift */; }; + 2E43A3D221BE9587BC19C3F1 /* MatrixEntityRegexTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */; }; + 2E8C6672D0EE7D5B1BEDB8E2 /* ServerConfirmationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7478623CECC9438014244BA /* ServerConfirmationScreen.swift */; }; + 2F1CF90A3460C153154427F0 /* RoomScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086B997409328F091EBA43CE /* RoomScreenUITests.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 */; }; + 2FEC6652055984389CE1BBEC /* TimelineProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50F03079F6B5EF9CA005F14 /* TimelineProxyProtocol.swift */; }; + 3041EBA2660F28FFB7BDA339 /* EncryptionResetScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0FF9CB3EFA753277291F609 /* EncryptionResetScreenCoordinator.swift */; }; + 3042527CB344A9EF1157FC26 /* AudioRecorderStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C55CC239AE12339C565F6C9A /* AudioRecorderStateTests.swift */; }; + 308BD9343B95657FAA583FB7 /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 19CD5B074D7DD44AF4C58BB6 /* SwiftState */; }; + 30CC1DB7CE357659C82AA115 /* MediaProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85EB16E7FE59A947CA441531 /* MediaProviderProtocol.swift */; }; + 30CC4F796B27BE8B1DFDBF5A /* NSEUserSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEAA2832D93EC7D2608703FB /* NSEUserSession.swift */; }; + 30E5628F74AD3C27A061BF25 /* QRCodeLoginScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BC1B7CB061C9865B2B91B56 /* QRCodeLoginScreenViewModel.swift */; }; + 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 */; }; + 32B7891D937377A59606EDFC /* UserFlowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21DD8599815136EFF5B73F38 /* UserFlowTests.swift */; }; + 32FC143630CE22A9E403370B /* MockAuthenticationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA38899517F08FE2AF34EB45 /* MockAuthenticationService.swift */; }; + 339BC18777912E1989F2F17D /* Section.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584A61D9C459FAFEF038A7C0 /* Section.swift */; }; + 33CAC1226DFB8B5D8447D286 /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 1BCD21310B997A6837B854D6 /* GZIP */; }; + 33F1FB19F222BA9930AB1A00 /* RoomListFiltersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6372DD10DED30E7AD7BCE21 /* RoomListFiltersView.swift */; }; + 340D39DB87F3800D53A6A621 /* EmojiPickerScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00245D40CD90FD71D6A05239 /* EmojiPickerScreen.swift */; }; + 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 */; }; + 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 */; }; + 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 */; }; + 36AC963F2F04069B7FF1AA0C /* UIConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */; }; + 36AD4DD4C798E22584ED3200 /* SentrySwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = 75361A9D8A3C5501EADB225D /* SentrySwiftUI */; }; + 36CD6E11B37396E14F032CB6 /* Version in Frameworks */ = {isa = PBXBuildFile; productRef = A05AF81DDD14AD58CB0E1B9B /* Version */; }; + 36DE961B784087D5E18EF9BA /* LogViewerScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A07692536D66E3DA32C4964 /* LogViewerScreen.swift */; }; + 370AF5BFCD4384DD455479B6 /* ElementCallWidgetDriverProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6C11AD9813045E44F950410 /* ElementCallWidgetDriverProtocol.swift */; }; + 37906355E207DB5703754675 /* AppLockSetupBiometricsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9F893F4A111CB7BA5C96949 /* AppLockSetupBiometricsScreenViewModel.swift */; }; + 37D789F24199B32E3FD1AA7B /* FileRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 216F0DDC98F2A2C162D09C28 /* FileRoomTimelineItemContent.swift */; }; + 37E47F5101C0C036289D3807 /* DSWaveformImageViews in Frameworks */ = {isa = PBXBuildFile; productRef = 2A4106A0A96DC4C273128AA5 /* DSWaveformImageViews */; }; + 384D6B9A7DFD7260139D6852 /* UITestsNotificationCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBEB8D9F4940E161B18FE4BC /* UITestsNotificationCenter.swift */; }; + 38546A6010A2CF240EC9AF73 /* BindableState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA1D2CBAEA5D0BD00B90D1B /* BindableState.swift */; }; + 386720B603F87D156DB01FB2 /* VoiceMessageMediaManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40076C770A5FB83325252973 /* VoiceMessageMediaManager.swift */; }; + 38896D54D6D675534E606195 /* RoomTimelineControllerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6FCC416A3BFE73DF7B3E6BF /* RoomTimelineControllerFactory.swift */; }; + 388D39ED9FE1122EA6D76BF2 /* Common.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1BC84BA0AF11C2128D58ABD /* Common.swift */; }; + 3895969759E68FAB90C63EF7 /* ElementCallServiceConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 406C90AF8C3E98DF5D4E5430 /* ElementCallServiceConstants.swift */; }; + 38CC67C7673FA97C21CCD5B5 /* WebRegistrationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B065EC39C99C1303A101C1C /* WebRegistrationScreen.swift */; }; + 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 */; }; + 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 */; }; + 3A7DD0D13B0FB8876D69D829 /* TextBasedRoomTimelineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AB2C848BB9A7A9B618B7B89 /* TextBasedRoomTimelineTests.swift */; }; + 3AA9E878FDCFF85664AC071F /* ComposerDraftService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D70253004A5AEC9C73D6A4F /* ComposerDraftService.swift */; }; + 3B0F9B57D25B07E66F15762A /* MediaUploadPreviewScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2E7C987AE5DC9087BB19F7D /* MediaUploadPreviewScreenModels.swift */; }; + 3B277D9538090766DA6C4566 /* StateRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2AF1828A5B76B7C371240FE /* StateRoomTimelineView.swift */; }; + 3B28408450BCAED911283AA2 /* UserPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35FA991289149D31F4286747 /* UserPreference.swift */; }; + 3B98049F56025726FB646ABD /* SwipeToReplyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B0E0B55E2EE75AF67029924 /* SwipeToReplyView.swift */; }; + 3C31E1A65EEB61E72E1113B4 /* AudioRecorderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEC57C204D77908E355EF42 /* AudioRecorderProtocol.swift */; }; + 3C549A0BF39F8A854D45D9FD /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 0DD568A494247444A4B56031 /* Kingfisher */; }; + 3C73442084BF8A6939F0F80B /* AnalyticsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5445FCE0CE15E634FDC1A2E2 /* AnalyticsService.swift */; }; + 3CE4C5071B6D2576E2473989 /* OrderedSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62B07B296D7A9D2F09120853 /* OrderedSet.swift */; }; + 3D72F5F9109AAA257542456B /* CallInviteRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664ABD745A746C45CB842158 /* CallInviteRoomTimelineView.swift */; }; + 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 */; }; + 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 */; }; + 3ED2725734568F6B8CC87544 /* AttributedStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5C6FBF97B6EED3D4FA5EFF /* AttributedStringBuilder.swift */; }; + 3F2148F11164C7C5609984EB /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 2B788C81F6369D164ADEB917 /* GZIP */; }; + 3F327A62D233933F54F0F33A /* SwiftOGG in Frameworks */ = {isa = PBXBuildFile; productRef = 3FE40E79C36E7903121E6E3B /* SwiftOGG */; }; + 3F70E237CE4C3FAB02FC227F /* NotificationConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = C830A64609CBD152F06E0457 /* NotificationConstants.swift */; }; + 3F997171C3C79A45E92BF9EF /* ElementWellKnown.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79FAC366FF299BCC555D756E /* ElementWellKnown.swift */; }; + 401BB28CD6B7DD6B4E7863E7 /* ServerConfirmationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9342F5D6729627B6393AF853 /* ServerConfirmationScreenModels.swift */; }; + 407DCE030E0F9B7C9861D38A /* LRUCache in Frameworks */ = {isa = PBXBuildFile; productRef = 1081D3630AAD3ACEDDEC3A98 /* LRUCache */; }; + 40B79D20A873620F7F128A2C /* UserPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35FA991289149D31F4286747 /* UserPreference.swift */; }; + 414F50CFCFEEE2611127DCFB /* RestorationToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3558A15CFB934F9229301527 /* RestorationToken.swift */; }; + 41CE5E1289C8768FC5B6490C /* RoomTimelineItemViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C2D52E36AD614B3C003EF6 /* RoomTimelineItemViewState.swift */; }; + 41DFDD212D1BE57CA50D783B /* KZFileWatchers in Frameworks */ = {isa = PBXBuildFile; productRef = 81DB3AB6CE996AB3954F4F03 /* KZFileWatchers */; }; + 41F553349AF44567184822D8 /* APNSPayload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D670124FC3E84F23A62CCF /* APNSPayload.swift */; }; + 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 */; }; + 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 */; }; + 43F06DF42EC00B3CE2B020A4 /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC3F82523D6F48B926D6AF68 /* AppSettings.swift */; }; + 43F35A7E5703D64DB0519C59 /* ServerSelectionScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD469F7513574341181F7EAA /* ServerSelectionScreen.swift */; }; + 440123E29E2F9B001A775BBE /* TimelineItemProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */; }; + 44121202B4A260C98BF615A7 /* RoomMembersListScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5B7A755E985FA14469E86B2 /* RoomMembersListScreenUITests.swift */; }; + 44BDD670FF9095ACE240A3A2 /* VoiceMessageMediaManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC4F10BDD56FA77FEC742333 /* VoiceMessageMediaManagerTests.swift */; }; + 44DA28B1E1F9C97C5795F7B3 /* AppLockSetupUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8A1BBEF7318CA6B6ACCF4AE /* AppLockSetupUITests.swift */; }; + 44F0E1B576C7599DF8022071 /* WysiwygComposer in Frameworks */ = {isa = PBXBuildFile; productRef = CA07D57389DACE18AEB6A5E2 /* WysiwygComposer */; }; + 454311EAC17D778E19F46592 /* NotificationPermissionsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91868EB98818044E6FEBE532 /* NotificationPermissionsScreenCoordinator.swift */; }; + 454F8DDC4442C0DE54094902 /* LABiometryType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3F219838588C62198E726E3 /* LABiometryType.swift */; }; + 4557192F5B15A8D9BB920232 /* AdvancedSettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E492690C8B27A892C194CC4 /* AdvancedSettingsScreenCoordinator.swift */; }; + 46562110EE202E580A5FFD9C /* RoomScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93CF7B19FFCF8EFBE0A8696A /* RoomScreenViewModelTests.swift */; }; + 4681820102DAC8BA586357D4 /* VoiceMessageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB8D7926A5684E18196B538 /* VoiceMessageCache.swift */; }; + 46A183C6125A669AEB005699 /* UserProfileScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F134D2D91DFF732FB75B2CB7 /* UserProfileScreenViewModelProtocol.swift */; }; + 46A261AA898344A1F3C406B1 /* ReportContentScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CCE3636E3D01477C8B2E9D0 /* ReportContentScreenModels.swift */; }; + 46A6DB0F78FB399BD59E2D41 /* EncryptionKeyProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E78FC546F28E045A560F2963 /* EncryptionKeyProviderProtocol.swift */; }; + 46BA7F4B4D3A7164DED44B88 /* FullscreenDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 565F1B2B300597C616B37888 /* FullscreenDialog.swift */; }; + 46C9F8FE3810A04A005FE16B /* AudioPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B19B2BCC779ED934E0BBC2A /* AudioPlayer.swift */; }; + 46FCD999E92D9717D24AAB94 /* QRCodeLoginScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDEDD4D2DE0646DA724985D5 /* QRCodeLoginScreenModels.swift */; }; + 4715FE33667C5899E64DD0E6 /* ResolveVerifiedUserSendFailureScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97287090CA64DAA95386ECED /* ResolveVerifiedUserSendFailureScreen.swift */; }; + 4716587A9BA69ED8FD1B986B /* PollOptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6B19D10B102956066AF117B /* PollOptionView.swift */; }; + 47305C0911C9E1AA774A4000 /* TemplateScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA90BD288E5AE6BC643AFDDF /* TemplateScreenCoordinator.swift */; }; + 4799A852132F1744E2825994 /* CreateRoomViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 340179A0FC1AD4AEDA7FC134 /* CreateRoomViewModelProtocol.swift */; }; + 4807E8F51DB54F56B25E1C7E /* AppLockSetupSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D8C38663020DF2EB2D13F5E /* AppLockSetupSettingsScreenViewModel.swift */; }; + 48416BBEB8DDF3E4DED0EDB6 /* ElementCallServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FC8B21E86B137BE4E91F82A /* ElementCallServiceProtocol.swift */; }; + 484202C5D50983442D24D061 /* AttributedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52BD6ED18E2EB61E28C340AD /* AttributedString.swift */; }; + 489BB6A733D3DA0FE7062650 /* IdentityConfirmationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C71B9802433F1B4252291BB /* IdentityConfirmationScreenViewModelProtocol.swift */; }; + 491D62ACD19E6F134B1766AF /* RoomNotificationSettingsUserDefinedScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3203C6566DC17B7AECC1B7FD /* RoomNotificationSettingsUserDefinedScreen.swift */; }; + 492274DA6691EE985C2FCCAA /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 67E7A6F388D3BF85767609D9 /* Sentry */; }; + 4940B439681767BE9D78CFDB /* AppLockSetupBiometricsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52F5EE5DE3B55D59299DB5BC /* AppLockSetupBiometricsScreenViewModelTests.swift */; }; + 4949C8C12669D1B5E082366E /* QRCodeLoginScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA9EA59D5C0DA1BFC7B3621 /* QRCodeLoginScreen.swift */; }; + 49500BBA1CD65A5AE252D970 /* RoomDirectorySearchScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41BB37D96C3EA18F3CE8675D /* RoomDirectorySearchScreenModels.swift */; }; + 4A4110369DBB79E4A314F415 /* ComposerToolbarViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0618820D26F9871A4BBB40E /* ComposerToolbarViewModelProtocol.swift */; }; + 4A618590DEB72C4F186BFED4 /* UserSessionFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C99FDEEB71173C4C6FA2734C /* UserSessionFlowCoordinator.swift */; }; + 4A8287E5281B44A8754BE509 /* SessionVerificationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED33988DA4FD4FC666800106 /* SessionVerificationScreenViewModel.swift */; }; + 4A85928E27D4C1A548A06EE9 /* StartChatScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 052B2F924572AFD70B5F500E /* StartChatScreenViewModel.swift */; }; + 4A9CEEE612D6D8B3DDBD28BA /* RoomListFilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24EC819497BB5F8C4998D760 /* RoomListFilterView.swift */; }; + 4AAA8606FBA290E23D15422E /* AvatarHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC743C7A85E3171BCBF0A653 /* AvatarHeaderView.swift */; }; + 4AD2B5426DBED97196AA4783 /* DeactivateAccountScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82EE3B877D91030248B1242D /* DeactivateAccountScreenViewModelProtocol.swift */; }; + 4B978C09567387EF4366BD7A /* MediaLoaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EF1AC723C2609C7705569CA /* MediaLoaderTests.swift */; }; + 4BAB8222DBA0B4207D1223E0 /* NotificationSettingsProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 382B50F7E379B3DBBD174364 /* NotificationSettingsProxyMock.swift */; }; + 4BB282209EA82015D0DF8F89 /* NavigationStackCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C698E30698EC59302A8EEBD /* NavigationStackCoordinatorTests.swift */; }; + 4BB51476A29E7E27BC14EA22 /* UserDetailsEditScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 022E6BD64CB4610B9C95FC02 /* UserDetailsEditScreenViewModel.swift */; }; + 4BBF6C8E3EFC944B55231B19 /* AppMediatorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05AF58372CA884A789EB9C5A /* AppMediatorProtocol.swift */; }; + 4C356F5CCB4CDC99BFA45185 /* AppLockSetupPINScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7884BD256C091EB511B2EDF /* AppLockSetupPINScreenViewModelProtocol.swift */; }; + 4C5A638DAA8AF64565BA4866 /* EncryptedRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5351EBD7A0B9610548E4B7B2 /* EncryptedRoomTimelineItem.swift */; }; + 4C8C0C9FC10BA73AB7780534 /* RoomListFiltersStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AE0C9653870803E4F91F474 /* RoomListFiltersStateTests.swift */; }; + 4CE638FD837ED72CD98AD9A9 /* AppHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E4AB573FAEBB7B853DD04C /* AppHooks.swift */; }; + 4D0F4385B7DDB68C66C78857 /* FormattedBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = C258C9C815272911A5B132C3 /* FormattedBodyText.swift */; }; + 4D23D41B8109E010304050F8 /* QRCodeLoginScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA551A98778CEE7366838CE2 /* QRCodeLoginScreenCoordinator.swift */; }; + 4D4D236F0BBCDC4D2CBCCBB5 /* RoomChangePermissionsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = C729D95CB4588D4D9AAC3DFA /* RoomChangePermissionsScreenModels.swift */; }; + 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 */; }; + 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 */; }; + 4EA1CE0E88EA68E862FF0EA2 /* NotificationSettingsEditScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B564D748B67A156F413CD97 /* NotificationSettingsEditScreenModels.swift */; }; + 4EAC427267424192964B16B3 /* AppSettingsHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13BE9781699FB510E9263192 /* AppSettingsHook.swift */; }; + 4F2DF6138E87A4B8C2488CA3 /* VoiceMessageCacheProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43A84EE187D0C772E18A4E39 /* VoiceMessageCacheProtocol.swift */; }; + 4FC085B1E5D1EB804495E2F4 /* MockMediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FD6E621CC5E6D4830D96D2D /* MockMediaProvider.swift */; }; + 4FDC8A9764CFDA90CE035725 /* Duration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FB2253D36E81E045E1CB432 /* Duration.swift */; }; + 4FE688FE9375B2FBF424146A /* TextBasedRoomTimelineViewProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6EA0D8B0BBD8805F7D5A133 /* TextBasedRoomTimelineViewProtocol.swift */; }; + 4FF90E2242DBD596E1ED2E27 /* AppCoordinatorStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077D7C3BE199B6E5DDEC07EC /* AppCoordinatorStateMachine.swift */; }; + 4FFDC274824F7CC0BBDF581E /* BugReportScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C2BCE0BC1FC69C1B36E688 /* BugReportScreenModels.swift */; }; + 50381244BA280451771BE3ED /* PINTextFieldTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF13BFD415CA84B1272E94F8 /* PINTextFieldTests.swift */; }; + 50539366B408780B232C1910 /* EstimatedWaveformView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD0FF64B0E6470F66F42E182 /* EstimatedWaveformView.swift */; }; + 50C90117FE25390BFBD40173 /* RustTracing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 542D4F49FABA056DEEEB3400 /* RustTracing.swift */; }; + 5100F53E6884A15F9BA07CC3 /* AttributedStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37CA26F55123E36B50DB0B3A /* AttributedStringTests.swift */; }; + 5139F4BD5A5DF6F8D11A9BDE /* NotificationPermissionsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D0BA44B1838E65B507B277 /* NotificationPermissionsScreen.swift */; }; + 518C93DC6516D3D018DE065F /* UNNotificationRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49E751D7EDB6043238111D90 /* UNNotificationRequest.swift */; }; + 51B3B19FA5F91B455C807BA7 /* RoomPollsHistoryScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E964AF2DFEB31E2B799999F /* RoomPollsHistoryScreenModels.swift */; }; + 523C6800ED85D5810CF18C19 /* OIDCAccountSettingsPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1D737F4672021D0A7D218CD /* OIDCAccountSettingsPresenter.swift */; }; + 52473A4D7B1FBD4CD1E770C8 /* MatrixEntityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */; }; + 5341D48F833E3E30F16FA2A3 /* SeparatorRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2910422CB628D3B2BBE47449 /* SeparatorRoomTimelineView.swift */; }; + 5375902175B2FEA2949D7D74 /* LoginScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */; }; + 53A55748D5F587C9061F98BF /* ServerConfigurationScreenViewStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277C20CDD5B64510401B6D0D /* ServerConfigurationScreenViewStateTests.swift */; }; + 53A59720F4729D9BBFFB7CAB /* NotificationSettingsEditScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD9CB3B9DFA353AB2B7CD9F8 /* NotificationSettingsEditScreenCoordinator.swift */; }; + 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 */; }; + 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 */; }; + 564910A38858306301C1C21E /* DeactivateAccountScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A1009E4A78F86DA42E1EAF0 /* DeactivateAccountScreenCoordinator.swift */; }; + 564BF06B3E93D6DD55F903B2 /* CreateRoomCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C618CA2B6C8758B06C88013C /* CreateRoomCoordinator.swift */; }; + 565868808A1DA565707394ED /* CurrentValuePublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */; }; + 56DACDD379A86A1F5DEFE7BE /* AuthenticationServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E75948AA1FE1D1A7809931F /* AuthenticationServiceProtocol.swift */; }; + 56F0A22972A3BB519DA2261C /* HomeScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */; }; + 5710AAB27D5D866292C1FE06 /* SessionVerificationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF848B41DAF1066F3054D4A1 /* SessionVerificationScreenModels.swift */; }; + 5732395A4F71F51F9C754C5A /* ElementCallService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33AE897D86784CCA5E4E9227 /* ElementCallService.swift */; }; + 5780E444F405AA1304E1C23E /* DeveloperOptionsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E521D6C2BF8DF0DFB35146 /* DeveloperOptionsScreen.swift */; }; + 583A41A4BE76E2E9E0B97881 /* ResolveVerifiedUserSendFailureScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5AEB5907E24092D741718AF /* ResolveVerifiedUserSendFailureScreenCoordinator.swift */; }; + 588411C8FD72B2A2DFE5F7DE /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = E992D7B8BE54B2AB454613AF /* XCUIElement.swift */; }; + 5894C2514400A4FBC9327632 /* ServerConfirmationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03277E40D0E0DE0712021A71 /* ServerConfirmationScreenCoordinator.swift */; }; + 5897A59DDBD3592282092223 /* MediaSourceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49B9785E3AD7D1C15A29F2F /* MediaSourceProxy.swift */; }; + 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 */; }; + 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 */; }; + 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 */; }; + 5C8AFBF168A41E20835F3B86 /* LoginScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DB34B0C74CD242FED9DD069 /* LoginScreenUITests.swift */; }; + 5D27B6537591471A42C89027 /* EmoteRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 450E04B2A976CC4C8CC1807C /* EmoteRoomTimelineItem.swift */; }; + 5D52925FEB1B780C65B0529F /* PinnedEventsTimelineScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA4F6D7000EDCD187E0989E7 /* PinnedEventsTimelineScreen.swift */; }; + 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 */; }; + 5DD0EF30070DC0A82C5CCD33 /* RoomMembersListManageMemberSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC853F9B4FBE039D2C16EC6B /* RoomMembersListManageMemberSheet.swift */; }; + 5DD85A0FE3D85AEC3C7EFE36 /* DeveloperOptionsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C7C7CFA6B2A62A685FF6CE3 /* DeveloperOptionsScreenCoordinator.swift */; }; + 5EE1D4E316D66943E97FDCF2 /* BloomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7BEB970F500BFB248443FA1 /* BloomView.swift */; }; + 5F06AD3C66884CE793AE6119 /* FileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */; }; + 5F0B5797D1BFF2A51084B4C3 /* PinnedEventsTimelineScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86D7CD5CA270BFC3EBB450CA /* PinnedEventsTimelineScreenViewModel.swift */; }; + 5F5488FBC9CFEB6F433D74A4 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7109E709A7738E6BCC4553E6 /* Localizable.strings */; }; + 5FCD8AFA364206EE32B909A3 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = B050A6B233D95807A09289E7 /* Settings.bundle */; }; + 601AB75BD52B0B4276CEB84A /* SessionVerificationScreenStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 161CD412E75F4086F422AE39 /* SessionVerificationScreenStateMachine.swift */; }; + 60ED66E63A169E47489348A8 /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 886A0A498FA01E8EDD451D05 /* Sentry */; }; + 6146996D5C4DDD5DA816FC87 /* AuthenticationTextFieldStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCACD75595C40EACD6AD4A74 /* AuthenticationTextFieldStyle.swift */; }; + 617624A97BDBB75ED3DD8156 /* RoomScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */; }; + 6189B4ABD535CE526FA1107B /* StartChatViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DF438EAFC732D2D95D34BF6 /* StartChatViewModelTests.swift */; }; + 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 */; }; + 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 */; }; + 62A7FC3A0191BC7181AA432B /* AudioRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 907FA4DE17DEA1A3738EFB83 /* AudioRecorder.swift */; }; + 62C5876C4254C58C2086F0DE /* HomeScreenContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3B4B58B79A6FA250B24A1EC /* HomeScreenContent.swift */; }; + 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 */; }; + 64D05250CEDE8B604119F6E6 /* Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 981663D961C94270FA035FD0 /* Alert.swift */; }; + 64E541F88F35BD126C4AFCA1 /* AppLockScreenPINKeypad.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38345442415E07A931197C55 /* AppLockScreenPINKeypad.swift */; }; + 64EE9D2CF7AD02EE53983CE1 /* FileRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F75EF13F49DD2204E760910 /* FileRoomTimelineView.swift */; }; + 651341E67C3514F9811A1EC1 /* LoginScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05F598B1B346DAF223651C91 /* LoginScreenCoordinator.swift */; }; + 652ACCF104A8CEF30788963C /* NotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1423AB065857FA546444DB15 /* NotificationManager.swift */; }; + 6530865EB9A8C0F0AF0216DA /* ServerSelectionScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9501D11B4258DFA33BA3B40F /* ServerSelectionScreenModels.swift */; }; + 654E802C127B84554042903E /* AnalyticsSettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECD5FCBA169B6A82F501CA1B /* AnalyticsSettingsScreenViewModelProtocol.swift */; }; + 6583A95947E78767736CB51A /* TimelineTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8112846C9D9D3817689CBAF8 /* TimelineTableViewController.swift */; }; + 6586E1F1D5F0651D0638FFAF /* UserSessionMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4469F6AE311BDC439B3A5EC /* UserSessionMock.swift */; }; + 659E5B766F76FDEC1BF393A4 /* RoomDetailsEditScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E413F4CBD7BF0588F394A9DD /* RoomDetailsEditScreenViewModel.swift */; }; + 661EF50C1F7D4B0BC8A7AAE3 /* EmoteRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44ABA63DBE7F76C58260B43B /* EmoteRoomTimelineView.swift */; }; + 66357ECB73B1290E5490A012 /* WebRegistrationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F418426410F3823F3EB0828 /* WebRegistrationScreenViewModelProtocol.swift */; }; + 663E198678778F7426A9B27D /* Collection.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9FAFE1C2149E6AC8156ED2B /* Collection.swift */; }; + 67160204A8D362BB7D4AD259 /* Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693E16574C6F7F9FA1015A8C /* Search.swift */; }; + 6786C4B0936AC84D993B20BF /* NotificationSettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5F06F2F09B2EDD067DC2174 /* NotificationSettingsScreen.swift */; }; + 67C05C50AD734283374605E3 /* MatrixEntityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */; }; + 67D6E0700A9C1E676F6231F8 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = AD544C0FA48DFFB080920061 /* Collections */; }; + 67E9926C4572C54F59FCA91A /* AuthenticationFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9B069D7772DDF6513E0F1B8 /* AuthenticationFlowCoordinator.swift */; }; + 67EFF46180B939CBF389AECD /* TimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93C713D124FE915ABF47A6B7 /* TimelineView.swift */; }; + 6817EAD73DC1FFD8B943B5B9 /* HomeScreenRoomTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B73587C2E3CF5998361AE516 /* HomeScreenRoomTests.swift */; }; + 68184EF36396424FE19A727D /* MediaLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AFCE895ECFFA53FEE64D62B /* MediaLoader.swift */; }; + 6832733838C57A7D3FE8FEB5 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 78A5A8DE1E2B09C978C7F3B0 /* KeychainAccess */; }; + 6851B077B4C913CC12DB6E77 /* AppLockFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCE93F0CBF0D96B77111C413 /* AppLockFlowCoordinator.swift */; }; + 6860721DB3091BE08164C132 /* MapAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B48B7AD4908C5C374517B892 /* MapAssets.xcassets */; }; + 695825D20A761C678809345D /* MessageForwardingScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52135BD9E0E7A091688F627A /* MessageForwardingScreenModels.swift */; }; + 69A9B430397C15075D86193F /* UserPropertiesExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66AFD800AF033D8B0D11191A /* UserPropertiesExt.swift */; }; + 69B3C6010B42010F591FC3CB /* RoomRolesAndPermissionsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C1AF829F12FDC99717082D9 /* RoomRolesAndPermissionsScreenViewModel.swift */; }; + 69C7B956B74BEC3DB88224EA /* NavigationSplitCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78913D6E120D46138E97C107 /* NavigationSplitCoordinatorTests.swift */; }; + 69DE29C3E3180BB17D840690 /* ProgressCursorModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97C8E13A1FBA717B0C277ECC /* ProgressCursorModifier.swift */; }; + 6A0E7551E0D1793245F34CDD /* ClientError.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09A267106B9585D3D0CFC0D /* ClientError.swift */; }; + 6A54F52443EC52AC5CD772C0 /* JoinRoomScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 869A8A4632E511351BFE2EC4 /* JoinRoomScreen.swift */; }; + 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 */; }; + 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 */; }; + 6DC8E43BA04AC2AC4EB2EB97 /* AnalyticsPromptScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18486B87745B1811E7FBD3D2 /* AnalyticsPromptScreenModels.swift */; }; + 6E391F7F628D984AF44385D9 /* RoomAttachmentPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 128501375217576AF0FE3E92 /* RoomAttachmentPicker.swift */; }; + 6E47D126DD7585E8F8237CE7 /* LoadableAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */; }; + 6E4E401BE97AC241DA7C7716 /* AppLockSetupSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 502F986D57158674172C58E3 /* AppLockSetupSettingsScreenModels.swift */; }; + 6E63704717F17593A475D152 /* RoomNotificationSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA14564EE143F73F7E4D1F79 /* RoomNotificationSettingsScreenModels.swift */; }; + 6EB46C92ECFEAE71959D91D2 /* TimelineReplyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C25B6EBEB414431187D73B7 /* TimelineReplyView.swift */; }; + 6EC7A40A537CFB3D526A111C /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47EBB5D698CE9A25BB553A2D /* Strings.swift */; }; + 6F26CBC84AE87EB4068D398B /* LRUCache in Frameworks */ = {isa = PBXBuildFile; productRef = 78B28D75FF7AF8E6146DEE2A /* LRUCache */; }; + 6F2AB43A1EFAD8A97AF41A15 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = 9C73F37731C9FDED1BB24C1C /* Collections */; }; + 6F86349BDEAF4495EAE38931 /* PHGPostHogMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2AD8A56CD37E23071A2F4BF /* PHGPostHogMock.swift */; }; + 6FC10A00D268FCD48B631E37 /* ViewFrameReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFF7BF82A950B91BC5469E91 /* ViewFrameReader.swift */; }; + 6FD8053301C5FEFA82D2F246 /* URLComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BFDCA5A09EE70BC17F2EFA7 /* URLComponents.swift */; }; + 70394ECD2DCC70741538620D /* AccessibilityIdentifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */; }; + 70558528EF68CAAEF09972D5 /* RoomTimelineItemFixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = E96ED747FF90332EA1333C22 /* RoomTimelineItemFixtures.swift */; }; + 706289B086B0A6B0C211763F /* UITestsSignalling.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7F0192CE2F891141A25B49F /* UITestsSignalling.swift */; }; + 707E49BE07E8EB8A13C0EB1E /* SessionVerificationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FACD034DB52525A3CEF2BDF /* SessionVerificationScreen.swift */; }; + 709A9B52FC26B4CB86B8B020 /* EncryptedRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F06F70B9C433BAD4BC6B9F5 /* EncryptedRoomTimelineView.swift */; }; + 70B83D44043293B4B77440B9 /* PollFormScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB63761D9F9CE8B23CBD6179 /* PollFormScreenModels.swift */; }; + 71643093F87153F633A1B025 /* ThreadDecorator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DA4F09CB613C54FDC73AE6A /* ThreadDecorator.swift */; }; + 719E7AAD1F8E68F68F30FECD /* Task.swift in Sources */ = {isa = PBXBuildFile; fileRef = A40C19719687984FD9478FBE /* Task.swift */; }; + 71AC1CAAC23403FFE847F2C9 /* ComposerToolbarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C90514BE9B8ACCBCF0AD2489 /* ComposerToolbarViewModel.swift */; }; + 71B62C48B8079D49F3FBC845 /* ExpiringTaskRunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84B7A28A6606D58D1E38C55A /* ExpiringTaskRunnerTests.swift */; }; + 71C1347F23868324A4F43940 /* NavigationModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A22A05E472533ED3C5A31B3 /* NavigationModule.swift */; }; + 733E2B19AB1FDA3B93293A28 /* AppLockSetupPINScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3F275432954C8C6B1B7D966 /* AppLockSetupPINScreen.swift */; }; + 7354D094A4C59B555F407FA1 /* RustTracing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 542D4F49FABA056DEEEB3400 /* RustTracing.swift */; }; + 7361B011A79BF723D8C9782B /* EmojiCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C1A3D524D63815B28FA4D62 /* EmojiCategory.swift */; }; + 73F33E9776B7A50B65A031D2 /* AppLockSettingsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0BA67B3E4EF9D29D14A78CE /* AppLockSettingsScreenViewModelTests.swift */; }; + 73F547BEB41D3DAFAAF6E0AF /* UserProfileScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71E2E5103702D13361D09100 /* UserProfileScreenViewModelTests.swift */; }; + 7405B4824D45BA7C3D943E76 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D0CBC76C80E04345E11F2DB /* Application.swift */; }; + 743790BF6A5B0577EA74AF14 /* ReadMarkerRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF3D25B3EDB283B5807EADCF /* ReadMarkerRoomTimelineItem.swift */; }; + 748F482FEF4E04D61C39AAD7 /* EmojiPickerScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = F174A5627CDB3CAF280D1880 /* EmojiPickerScreenModels.swift */; }; + 7501442D52A65F73DF79FFD4 /* PaginationIndicatorRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B987FC3FDBAA0E1C5AA235C /* PaginationIndicatorRoomTimelineItem.swift */; }; + 754602A7B2AAD443C4228ED4 /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 997C7385E1A07E061D7E2100 /* GZIP */; }; + 755395927DDD6EBDDA5E217A /* SettingsFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28F7A6CEEA4A2815B0F0F55 /* SettingsFlowCoordinator.swift */; }; + 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 */; }; + 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 */; }; + 7640A4B412CACF15D143CCD4 /* Strings+SAS.swift in Sources */ = {isa = PBXBuildFile; fileRef = B172057567E049007A5C4D92 /* Strings+SAS.swift */; }; + 767D366C40F1311CFA333763 /* PillContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86376BEE425704AEE197CA54 /* PillContext.swift */; }; + 7691233E3572A9173FD96CB3 /* SecureBackupKeyBackupScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E88534A39781D76487D59DF /* SecureBackupKeyBackupScreenViewModelTests.swift */; }; + 7708976CEE6AFB5CFAEFBA68 /* PillTextAttachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CF1EE0AA78470C674554262 /* PillTextAttachment.swift */; }; + 7756C4E90CABE6F14F7920A0 /* BugReportUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6FEA87EA3752203065ECE27 /* BugReportUITests.swift */; }; + 77574A519A4E484880053EAD /* IdentityConfirmationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FDF541AE914059942B575B4 /* IdentityConfirmationScreenModels.swift */; }; + 77693820498ABF3508814D49 /* AppLockServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD97F9661ABF08CE002054A2 /* AppLockServiceTests.swift */; }; + 77920AFA8091AC6B9F190C90 /* Signposter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752A0EB49BF5BCEA37EDF7A3 /* Signposter.swift */; }; + 77BB228AEA861E50FFD6A228 /* HomeScreenEmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0FEA560929DD73FFEF8C3DF /* HomeScreenEmptyStateView.swift */; }; + 77C1A2F49CD90D3EFDF376E5 /* MapTilerURLBuildersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 376D941BF8BB294389C0DE24 /* MapTilerURLBuildersTests.swift */; }; + 77D7DAA41AAB36800C1F2E2D /* RoomTimelineProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */; }; + 77FACC29F98FE2E65BBB6A5F /* ServerSelectionUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 054F469E433864CC6FE6EE8E /* ServerSelectionUITests.swift */; }; + 7807B1DEE32617896886A8E5 /* FormattingToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE1E6FAA3719E9B7A2D5510B /* FormattingToolbar.swift */; }; + 784592335560C2E91D32D177 /* DeveloperOptionsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06B098A612DCB5A7358EECD5 /* DeveloperOptionsScreenModels.swift */; }; + 785613C0C092B532198EB3BB /* TimelineStartRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44ECC9D66400727DFFEE12E8 /* TimelineStartRoomTimelineView.swift */; }; + 7856DE3EA4580AE0329986EB /* ComposerDraftServiceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E600B315B920B9687F8EE1B /* ComposerDraftServiceMock.swift */; }; + 78A3D84BA47DAC69B4D0A34C /* CollapsibleRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBF273BC2BFB9F3EEFA988B /* CollapsibleRoomTimelineView.swift */; }; + 795A854F63301DC6B46217B9 /* AccessibilityIdentifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */; }; + 79741C1953269FF1A211D246 /* RoomPollsHistoryScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0E14FF533D25A0692F7CEB0 /* RoomPollsHistoryScreenViewModel.swift */; }; + 798BF3072137833FBD3F4C96 /* TimelineDeliveryStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F91544AC136BF6477BDAB8 /* TimelineDeliveryStatusView.swift */; }; + 79959F8E45C3749997482A7F /* TimelineItemBubbledStylerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A459AE4B6566B2FA99E86B2 /* TimelineItemBubbledStylerView.swift */; }; + 7A02EB29F3B993AB20E0A198 /* RoomPollsHistoryScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C8C368A611B9CB79C7F5FA /* RoomPollsHistoryScreen.swift */; }; + 7A0D335D38ECA095A575B4F7 /* TimelineStyler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DB0E533508094156D8024C3 /* TimelineStyler.swift */; }; + 7A170A5A4A352954BB2A1B96 /* AuthenticationStartScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24E8C8817F59BEC7E358EB78 /* AuthenticationStartScreen.swift */; }; + 7A25D6926A2C01DB8D0D67A5 /* BadgeLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A028783CFFF861C5E44FFB1 /* BadgeLabel.swift */; }; + 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 */; }; + 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 */; }; + 7B66DA4E7E5FE4D1A0FCEAA4 /* JoinRoomScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEAB5662310AE73D93815134 /* JoinRoomScreenViewModelProtocol.swift */; }; + 7BB31E67648CF32D2AB5E502 /* RoomScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CE3C90E487B255B735D73C8 /* RoomScreenViewModel.swift */; }; + 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 */; }; + 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 */; }; + 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 */; }; + 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 */; }; + 7F61F9ACD5EC9E845EF3EFBF /* BugReportServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFFD3200F9960D4996159F10 /* BugReportServiceTests.swift */; }; + 7F7EA51A9A43125A8CB6AC90 /* NotificationSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D560DDA3B20C82766ACFAD /* NotificationSettingsScreenViewModel.swift */; }; + 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 */; }; + 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 */; }; + 80DEA2A4B20F9E279EAE6B2B /* UserProfile+Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAD01F7FC2BBAC7351948595 /* UserProfile+Mock.swift */; }; + 80F6C8EFCA4564B67F0D34B0 /* DeactivateAccountScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D77F75B3E9F99864048A422A /* DeactivateAccountScreenViewModelTests.swift */; }; + 81A7C020CB5F6232242A8414 /* UserSessionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36C0A6D59717193F49EA986 /* UserSessionTests.swift */; }; + 8285FF4B2C2331758C437FF7 /* ReportContentScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 713B48DBF65DE4B0DD445D66 /* ReportContentScreenViewModelProtocol.swift */; }; + 828EA5009557C2B9DCD4CA0F /* UserDiscoverySection.swift in Sources */ = {isa = PBXBuildFile; fileRef = D071F86CD47582B9196C9D16 /* UserDiscoverySection.swift */; }; + 832A4EA1094B8FE423A08700 /* RoomChangeRolesScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B2A421198FD20AAAED20004 /* RoomChangeRolesScreen.swift */; }; + 8358D145F9BF94F412BEDCA8 /* RoomRolesAndPermissionsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DE7969EBCAF078813E18EA1 /* RoomRolesAndPermissionsScreenModels.swift */; }; + 83A4DAB181C56987C3E804FF /* MapTilerStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0B9F5BC4C80543DE7228B9D /* MapTilerStyle.swift */; }; + 83B17A44D3E7E6DF22D9A2A4 /* RoomModerationRole.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B32BBA8887BD7A5C4ECF16F /* RoomModerationRole.swift */; }; + 84226AD2E1F1FBC965F3B09E /* UnitTestsAppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A8E19C4645D3F5F9FB02355 /* UnitTestsAppCoordinator.swift */; }; + 8446C2A7ECEFDA79F622725F /* TimelineReactionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54AD70D6E03D2031AE1B5A52 /* TimelineReactionsView.swift */; }; + 8478992479B296C45150208F /* AppLockScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC0275CEE9CA078B34028BDF /* AppLockScreenViewModelTests.swift */; }; + 847DE3A7EB9FCA2C429C6E85 /* PINTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D1D4A6D451F43A03CACD01D /* PINTextField.swift */; }; + 84C631E734FD2555B39B681C /* RoomRolesAndPermissionsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48FEFF746DB341CDB18D7AAA /* RoomRolesAndPermissionsScreenViewModelTests.swift */; }; + 84CAE3E96D93194DA06B9194 /* CallScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD9AD6AE5FC868962F090740 /* CallScreenViewModelProtocol.swift */; }; + 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 */; }; + 864C0D3A4077BF433DBC691F /* PollRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5281C5CDC4A712265A0B5FBF /* PollRoomTimelineItem.swift */; }; + 864C69CF951BF36D25BE0C03 /* DeveloperOptionsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D0A27607AB09784C8501B5C /* DeveloperOptionsScreenViewModelTests.swift */; }; + 8658F5034EAD7357CE7F9AC7 /* MatrixUserShareLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50E31AB0E77BB70E2BC77463 /* MatrixUserShareLink.swift */; }; + 865DD5CA474C6AE6C2BC008E /* NetworkMonitorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1575947B7A6FE08C57FE5EE4 /* NetworkMonitorProtocol.swift */; }; + 86675910612A12409262DFBD /* SessionVerificationStateMachineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1C22B1B5FA3A765EADB2CC9 /* SessionVerificationStateMachineTests.swift */; }; + 8691186F9B99BCDDB7CACDD8 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */; }; + 86F9D3028A1F4AE819D75560 /* RoomChangePermissionsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D879FC4E881E748BB9B34DC /* RoomChangePermissionsScreenCoordinator.swift */; }; + 872A6457DF573AF8CEAE927A /* LoginHomeserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9349F590E35CE514A71E6764 /* LoginHomeserver.swift */; }; + 874FEFB9D4A4AF447E0E086E /* AuthenticationStartScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0F7CCC4A9D1927223F559D5 /* AuthenticationStartScreenViewModelProtocol.swift */; }; + 878070573C7BF19E735707B4 /* RoomTimelineItemProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DE8D25D6A91030175D52A20 /* RoomTimelineItemProperties.swift */; }; + 87B4E59A4467F8EC75F82372 /* VoiceMessageRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B70A50C41C5871B4DB905E7E /* VoiceMessageRoomTimelineView.swift */; }; + 87CEA3E07B602705BC2D2A20 /* ClientBuilderHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AC0CD1CAFD3F8B057F9AEA5 /* ClientBuilderHook.swift */; }; + 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 */; }; + 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 */; }; + 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 */; }; + 899793EFC63DF93C3E0141E7 /* RoomMemberDetailsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FA60F848D1C14F873F9621A /* RoomMemberDetailsScreenCoordinator.swift */; }; + 89B909AC66B96FA054EF3C14 /* InvitedRoomProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E95B3BDB80531C85CD50AE6 /* InvitedRoomProxy.swift */; }; + 8A0BD60CA4A6004DB06B5403 /* MediaUploadingPreprocessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 669F35C505ACE1110589F875 /* MediaUploadingPreprocessor.swift */; }; + 8A5064CAC8E5F3B18645621D /* CallNotificationRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD6E082B0507FB28F966516A /* CallNotificationRoomTimelineView.swift */; }; + 8A6CB15C8FC68F557750BF54 /* AuthenticationClientBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F569CFB77E0D40BD82203D9 /* AuthenticationClientBuilder.swift */; }; + 8A83D715940378B9BA9F739E /* RoomInviterLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EB58E4E8D6D634C246AD5C2 /* RoomInviterLabel.swift */; }; + 8AA84EF202F2EFC8453A97BD /* SecureBackupRecoveryKeyScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 645E027C112740573D27765C /* SecureBackupRecoveryKeyScreenModels.swift */; }; + 8AB8ED1051216546CB35FA0E /* UserSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E5E9C044BEB7C70B1378E91 /* UserSession.swift */; }; + 8AC256AF0EC54658321C9241 /* LegalInformationScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E5725BC6C63604CB769145B /* LegalInformationScreenViewModelTests.swift */; }; + 8B1D5CE017EEC734CF5FE130 /* Encodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 260004737C573A56FA01E86E /* Encodable.swift */; }; + 8B408C574E35E1C9B43A50CE /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */; }; + 8B41D0357B91CD3B6F6A3BCA /* EmoteRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE378083653EF0C9B5E9D580 /* EmoteRoomTimelineItemContent.swift */; }; + 8B76191B9DDD1AC90A6E3A35 /* MediaFileHandleProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEC1D382565A4E9CAC2F14EA /* MediaFileHandleProxy.swift */; }; + 8BC8EF6705A78946C1F22891 /* SoftLogoutScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71A7D4DDEEE5D2CA0C8D63CD /* SoftLogoutScreen.swift */; }; + 8C050A8012E6078BEAEF5BC8 /* PillTextAttachmentData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 913C8E13B8B602C7B6C0C4AE /* PillTextAttachmentData.swift */; }; + 8C1A5ECAF895D4CAF8C4D461 /* AppActivityView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F21ED7205048668BEB44A38 /* AppActivityView.swift */; }; + 8C706DA7EAC0974CA2F8F1CD /* MentionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15748C254911E3654C93B0ED /* MentionBuilder.swift */; }; + 8C91D242BEEC657FABCC0B95 /* BlockedUsersScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8642512079EEFD622E3AA66B /* BlockedUsersScreenModels.swift */; }; + 8CC12086CBF91A7E10CDC205 /* HomeScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D653265D006E708E4E51AD64 /* HomeScreenCoordinator.swift */; }; + 8CFDA5F1562479CB3A34D277 /* RedactedRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91C8BD78F7B9247AC57FA1A3 /* RedactedRoomTimelineView.swift */; }; + 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 */; }; + 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 */; }; + 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 */; }; + 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 */; }; + 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 */; }; + 91ABC91758A6E4A5FAA2E9C4 /* ReadReceipt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */; }; + 91C6AC0E9D2B9C0C76CC6AD4 /* RoomDirectorySearchScreenScreenModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3984C93B8E9B10C92DADF9EE /* RoomDirectorySearchScreenScreenModelProtocol.swift */; }; + 9219640F4D980CFC5FE855AD /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 536E72DCBEEC4A1FE66CFDCE /* target.yml */; }; + 92720AB0DA9AB5EEF1DAF56B /* SecureBackupLogoutConfirmationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7DC017C3CB6B0F7C63F460F2 /* SecureBackupLogoutConfirmationScreenViewModel.swift */; }; + 9278EC51D24E57445B290521 /* AudioSessionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB284643AF7AB131E307DCE0 /* AudioSessionProtocol.swift */; }; + 92D9088B901CEBB1A99ECA4E /* RoomMemberProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */; }; + 934051B17A884AB0635DF81B /* BlockedUsersScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A010B8EAD1A9F6B4686DF2F4 /* BlockedUsersScreenViewModel.swift */; }; + 937985546F708339711ECDFC /* ComposerToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85666E40F7E817809B4FD787 /* ComposerToolbar.swift */; }; + 93875ADD456142D20823ED24 /* ServerSelectionViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDAA4472821985BF868CC21C /* ServerSelectionViewModelTests.swift */; }; + 93A549135E6C027A0D823BFE /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 593FBBF394712F2963E98A0B /* DTCoreText */; }; + 93AC1E8418D8C827671FB3A9 /* IdentityConfirmedScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 595EC503DA5517BBE6D39406 /* IdentityConfirmedScreenCoordinator.swift */; }; + 93BA4A81B6D893271101F9F0 /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = A7CA6F33C553805035C3B114 /* DeviceKit */; }; + 93BAF04D9CCBC0A8841414D0 /* NetworkMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D67E616BCA82D8A1258D488 /* NetworkMonitor.swift */; }; + 9408CE8B8865C0C8DD4C9869 /* NoticeRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD51B4D5173F7FC886F5360 /* NoticeRoomTimelineItemContent.swift */; }; + 9462C62798F47E39DCC182D2 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA89A2DD51B6BBE1DA55E263 /* Application.swift */; }; + 94A65DD8A353DF112EBEF67A /* SessionVerificationControllerProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D56469A9EE0CFA2B7BA9760 /* SessionVerificationControllerProxyProtocol.swift */; }; + 94D0F36A87E596A93C0C178A /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E89E530A8E92EC44301CA1 /* Bundle.swift */; }; + 94E15D018D70563FA4AB4E5A /* ComposerToolbarModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D3A7375AB22721C436EB056 /* ComposerToolbarModels.swift */; }; + 94F0B78928E952689ACDB271 /* NetworkMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D67E616BCA82D8A1258D488 /* NetworkMonitor.swift */; }; + 95690DDD9D547D3D842ACBE3 /* AnalyticsSettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BD371B60E07A5324B9507EF /* AnalyticsSettingsScreenCoordinator.swift */; }; + 9586E90A447C4896C0CA3A8E /* TimelineItemReplyDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE89A8BD65CCE3FCC925CA14 /* TimelineItemReplyDetails.swift */; }; + 95E7B236F7116CACE05A6BC9 /* BlockedUsersScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A16D0F226B1819D017531647 /* BlockedUsersScreenCoordinator.swift */; }; + 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 */; }; + 973C48F9E4EFB808F61BE401 /* LocationRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED49073BB1C1FC649DAC2CCD /* LocationRoomTimelineView.swift */; }; + 978BB24F2A5D31EE59EEC249 /* UserSessionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4134FEFE4EB55759017408 /* UserSessionProtocol.swift */; }; + 97969EF0B9C412CD38E5CA93 /* AppLockScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4005D82E9D27BAF006A8FE1 /* AppLockScreenViewModel.swift */; }; + 97BAEDD9054FB5F233EE928B /* EncryptionResetScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 306AB507E1027D6C5C147EB6 /* EncryptionResetScreenModels.swift */; }; + 981853650217B6C8ECDD998C /* NavigationRootCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */; }; + 983896D611ABF52A5C37498D /* RoomSummaryProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDB3227C7A74B734924942E9 /* RoomSummaryProvider.swift */; }; + 9847B056C1A216C314D21E68 /* AuthenticationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3A1AB5A84D843B6AC8D5F1E /* AuthenticationService.swift */; }; + 988BA75A182738150894A23F /* UserIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8AE4B3273BA189FDCD4055C /* UserIndicator.swift */; }; + 98EE4259A4A49BC757BA442C /* TimelineViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97B2ACA28A854E41AE3AC9AD /* TimelineViewModel.swift */; }; + 9905C1B1C6EFE38F3A6533F3 /* Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33B3F17996DFDF5F0181512 /* Data.swift */; }; + 9912F9EB2D6589141A2957B4 /* AppLockScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C44BBC892499BE45B074F89 /* AppLockScreenCoordinator.swift */; }; + 992F5E750F5030C4BA2D0D03 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 01C4C7DB37597D7D8379511A /* Assets.xcassets */; }; + 99ED42B8F8D6BFB1DBCF4C45 /* AnalyticsEvents in Frameworks */ = {isa = PBXBuildFile; productRef = D661CAB418C075A94306A792 /* AnalyticsEvents */; }; + 9A0326D2375075871D2AB537 /* ResolveVerifiedUserSendFailureScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 574CB70E82D7EAEA538E4135 /* ResolveVerifiedUserSendFailureScreenViewModel.swift */; }; + 9A3B0CDF097E3838FB1B9595 /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E89E530A8E92EC44301CA1 /* Bundle.swift */; }; + 9A4E3D5AA44B041DAC3A0D81 /* OIDCAuthenticationPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92390F9FA98255440A6BF5F8 /* OIDCAuthenticationPresenter.swift */; }; + 9AC5F8142413862A9E3A2D98 /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 531CE4334AC5CA8DFF6AEB84 /* DTCoreText */; }; + 9B03943616A1147539DF7F08 /* RoomChangePermissionsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D041A857614A9AE13C7795 /* RoomChangePermissionsScreenViewModelTests.swift */; }; + 9B356742E035D90A8BB5CABE /* ProposedViewSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DFE0E493FB55E5A62E7852A /* ProposedViewSize.swift */; }; + 9B872FF37DBE6BE054903831 /* MediaUploadPreviewScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D54E12B98252F6C527E31FEE /* MediaUploadPreviewScreenViewModelProtocol.swift */; }; + 9BB91CABB10D8FE90C491BCD /* StaticLocationScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C833673B334A0651AB46F30B /* StaticLocationScreenViewModelTests.swift */; }; + 9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */; }; + 9C4EC28A921486B1775D7F8C /* IdentityConfirmedScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 307702DD66E7DDCDD9214784 /* IdentityConfirmedScreen.swift */; }; + 9C55746D8F6A3E35CFCF4A7A /* AuthenticationStartLogo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 598F01EBD0C4CC550C644418 /* AuthenticationStartLogo.swift */; }; + 9CBB04365408F9D6F46BA3A7 /* PinnedEventsTimelineFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A54AAF72E821B4084B7E4298 /* PinnedEventsTimelineFlowCoordinator.swift */; }; + 9D2E03DB175A6AB14589076D /* AnalyticsEvents in Frameworks */ = {isa = PBXBuildFile; productRef = 2A3F7BCCB18C15B30CCA39A9 /* AnalyticsEvents */; }; + 9D79B94493FB32249F7E472F /* PlaceholderAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C705E605EF57C19DBE86FFA1 /* PlaceholderAvatarImage.swift */; }; + 9D9690D2FD4CD26FF670620F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C75EF87651B00A176AB08E97 /* AppDelegate.swift */; }; + 9DD5AA10E85137140FEA86A3 /* MediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */; }; + 9DD84E014ADFB2DD813022D5 /* RoomDetailsEditScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00E5B2CBEF8F96424F095508 /* RoomDetailsEditScreenViewModelTests.swift */; }; + 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 */; }; + 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 */; }; + 9FB41B0E8B2AA9B404E52C8B /* AppLockSetupBiometricsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CCC6C31102E1D8B9106DEDE /* AppLockSetupBiometricsScreenViewModelProtocol.swift */; }; + 9FBE1FB20171012260A32492 /* TimelineSenderAvatarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53FCCE44F96E0BC411A6CF0 /* TimelineSenderAvatarView.swift */; }; + 9FC820C410ED733CE6FC6616 /* WebRegistrationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6702BC84D3CC2421D78CD4E /* WebRegistrationScreenViewModel.swift */; }; + 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 */; }; + 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 */; }; + A14A9419105A1CD42F0511C4 /* UserIndicatorModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43005941B3A2C9671E23C85 /* UserIndicatorModalView.swift */; }; + 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 */; }; + A20364EE08D902E647C11FB3 /* WebRegistrationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7D851A10FDA55579960DC61 /* WebRegistrationScreenCoordinator.swift */; }; + A216C83ADCF32BA5EF8A6FBC /* InviteUsersViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845DDBDE5A0887E73D38B826 /* InviteUsersViewModelTests.swift */; }; + A2172B5A26976F9174228B8A /* AppHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E4AB573FAEBB7B853DD04C /* AppHooks.swift */; }; + A23B8B27A1436A1049EEF68E /* InfoPlistReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A580295A56B55A856CC4084 /* InfoPlistReader.swift */; }; + A2434D4DFB49A68E5CD0F53C /* MediaLoaderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A02406480C351B8C6E0682C /* MediaLoaderProtocol.swift */; }; + A33784831AD880A670CAA9F9 /* FileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */; }; + A36AD251013402EDBD666C75 /* AppMediatorMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BAC027034248429A438886B /* AppMediatorMock.swift */; }; + A37EED79941AD3B7140B3822 /* UIDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 287FC98AF2664EAD79C0D902 /* UIDevice.swift */; }; + A3A7A05E8F9B7EB0E1A09A2A /* SoftLogoutScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05596E4A11A8C9346E9E54AE /* SoftLogoutScreenCoordinator.swift */; }; + A3D7110C1E75E7B4A73BE71C /* VoiceMessageRecorderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93C94C30E3135BC9290DE13 /* VoiceMessageRecorderTests.swift */; }; + A439B456D0761D6541745CC3 /* NSRegularExpresion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95BAC0F6C9644336E9567EE6 /* NSRegularExpresion.swift */; }; + A440D4BC02088482EC633A88 /* KeychainControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5E94DCFEE803E5ABAE8ACCE /* KeychainControllerProtocol.swift */; }; + A494741843F087881299ACF0 /* RestorationToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3558A15CFB934F9229301527 /* RestorationToken.swift */; }; + A4AF12D9D8BA34B3B7B55B08 /* AuthenticationStartScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6663BFB9FDB8752562CD12CA /* AuthenticationStartScreenCoordinator.swift */; }; + A4B0BAD62A12ED76BD611B79 /* BadgeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1FA515B3B0D61EF1E907D2D /* BadgeView.swift */; }; + A4B123C635F70DDD4BC2FAC9 /* BlockedUsersScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E76A706B3EEA32B882DA5E2D /* BlockedUsersScreenViewModelProtocol.swift */; }; + A4C29D373986AFE4559696D5 /* SecureBackupKeyBackupScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4525E8C0FBDD27D1ACE90952 /* SecureBackupKeyBackupScreenViewModelProtocol.swift */; }; + A4E885358D7DD5A072A06824 /* PostHog in Frameworks */ = {isa = PBXBuildFile; productRef = CCE5BF78B125320CBF3BB834 /* PostHog */; }; + A52090A4FE0DB826578DFC03 /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0724EBDFE8BB4C9E5547C57D /* Client.swift */; }; + A5B9EF45C7B8ACEB4954AE36 /* LoginScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9780389F8A53E4D26E23DD03 /* LoginScreenViewModelProtocol.swift */; }; + A5D551E5691749066E0E0C44 /* RoomDetailsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 837B440C4705E4B899BCB899 /* RoomDetailsScreenViewModel.swift */; }; + A64B52D9F73F9A6B95AF24FE /* UserDetailsEditScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CD503F5E0938FE53C7C6E7 /* UserDetailsEditScreenCoordinator.swift */; }; + A6B83EB78F025D21B6EBA90C /* CompoundIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 044E501B8331B339874D1B96 /* CompoundIcon.swift */; }; + A6D4C5EEA85A6A0ABA1559D6 /* RoomDetailsEditScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16D09C79746BDCD9173EB3A7 /* RoomDetailsEditScreenModels.swift */; }; + 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 */; }; + 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 */; }; + A816F7087C495D85048AC50E /* RoomMemberDetailsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B6E30BB748F3F480F077969 /* RoomMemberDetailsScreenModels.swift */; }; + A851635B3255C6DC07034A12 /* RoomScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8108C8F0ACF6A7EB72D0117 /* RoomScreenCoordinator.swift */; }; + A8FA7671948E3DF27F320026 /* BugReportFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7367B3B9A8CAF902220F31D1 /* BugReportFlowCoordinator.swift */; }; + A93661C962B12942C08864B6 /* SwiftOGG in Frameworks */ = {isa = PBXBuildFile; productRef = 391D11F92DFC91666AA1503F /* SwiftOGG */; }; + A9482B967FC85DA611514D35 /* VoiceMessageRoomPlaybackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CCD41CD67DB5DA0D436BFE9 /* VoiceMessageRoomPlaybackView.swift */; }; + A969147E0EEE0E27EE226570 /* MediaUploadPreviewScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47F29139BC2A804CE5E0757E /* MediaUploadPreviewScreenViewModel.swift */; }; + A975D60EA49F6AF73308809F /* RoomMembersListScreenMemberCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC03209FDE8CE0810617BFFF /* RoomMembersListScreenMemberCell.swift */; }; + A9A5801D5EE3D4D91F6DDADB /* AnalyticsSettingsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58C2527813FDAE23E72A9063 /* AnalyticsSettingsScreenViewModelTests.swift */; }; + A9D349478F7D4A2B1E40CEF9 /* LegalInformationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8977176AB534AA41630395BC /* LegalInformationScreenViewModelProtocol.swift */; }; + 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 */; }; + 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 */; }; + AC1DB27A4134470846BE49F6 /* UserProfileScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BD116096CAA9139B95EEA9C /* UserProfileScreenViewModel.swift */; }; + AC69B6DF15FC451AB2945036 /* UserSessionStoreProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEBA759D1347CFFB3D84ED1F /* UserSessionStoreProtocol.swift */; }; + AC7AA215D60FBC307F984028 /* Consumable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 127A57D053CE8C87B5EFB089 /* Consumable.swift */; }; + AC90434798E7894370E80E66 /* SecureBackupScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D79BB714D28C9F588DD69353 /* SecureBackupScreenViewModelProtocol.swift */; }; + AD2A81B65A9F6163012086F1 /* MXLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111B698739E3410E2CDB7144 /* MXLog.swift */; }; + AD55E245FE686D7DB4C86406 /* RoomTimelineItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90F2F8998E5632668B0AD848 /* RoomTimelineItemView.swift */; }; + AE07F215EBC2B9CBF17AA54B /* TimelineItemMenuAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F1C3CBBC62C566DDF5E84C1 /* TimelineItemMenuAction.swift */; }; + AE1160076F663BF14E0E893A /* EffectsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4548A9BDE5CB3AB864BCA9F /* EffectsView.swift */; }; + AE1A73B24D63DA3D63DC4EE3 /* SessionVerificationControllerProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */; }; + AE5AAD9E32511544FDFA5560 /* WindowManagerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06F27F588F9059128E17C669 /* WindowManagerProtocol.swift */; }; + AF19D65A9C60C6B2646F3210 /* RedactedRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6E6BDF9D26DB05C88901416 /* RedactedRoomTimelineItem.swift */; }; + AF2ABA2794E376B64104C964 /* MockSoftLogoutScreenState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5644919DB2022397D9D5825A /* MockSoftLogoutScreenState.swift */; }; + AF33B9044498211C3D82F1E1 /* UNTextInputNotificationResponse+Creator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 130ED565A078F7E0B59D9D25 /* UNTextInputNotificationResponse+Creator.swift */; }; + AF8BFA37791E1756EE243E08 /* SettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8F0ED874DF8C9A51B0AB6F /* SettingsScreenCoordinator.swift */; }; + AFE2AB612A1460E49578D746 /* JoinRoomScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BDCCD2F6B405C14B9BCE94E /* JoinRoomScreenCoordinator.swift */; }; + B04E9EB589CE99C3929E817A /* HomeScreenRecoveryKeyConfirmationBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05512FB13987D221B7205DE0 /* HomeScreenRecoveryKeyConfirmationBanner.swift */; }; + B0CB16349B96262AA65A04AF /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 7731767AE437BA3BD2CC14A8 /* Sentry */; }; + B1069F361E604D5436AE9FFD /* StaticLocationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B06663F7858E45882E63471 /* StaticLocationScreen.swift */; }; + B10F7D5C237417DA160F4603 /* LongPressWithFeedback.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D9F148717D74F73BE724434 /* LongPressWithFeedback.swift */; }; + B13774779EA19FDD7A35A4A8 /* RoomRolesAndPermissionsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C28B70BEFD3676F11D5D51F /* RoomRolesAndPermissionsScreenCoordinator.swift */; }; + B1387648C6F71F1B98244803 /* SecureBackupRecoveryKeyScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 596AA8843AC1A234F3387767 /* SecureBackupRecoveryKeyScreenCoordinator.swift */; }; + 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 */; }; + 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 */; }; + B2F8E01ABA1BA30265B4ECBE /* RoundedCornerShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = 839E2C35DF3F9C7B54C3CE49 /* RoundedCornerShape.swift */; }; + B31E5493C99381D4E204438B /* RoomTimelineControllerFactoryMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = D479DF730528153665E5782E /* RoomTimelineControllerFactoryMock.swift */; }; + B3D652AA1654270742072FB3 /* DeveloperOptionsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86A6F283BC574FDB96ABBB07 /* DeveloperOptionsScreenViewModel.swift */; }; + B402708F8728DD0DB7C324E2 /* StartChatScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78910787F967CBC6042A101E /* StartChatScreenViewModelProtocol.swift */; }; + B444F9C184A377C1B481F07F /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = E992D7B8BE54B2AB454613AF /* XCUIElement.swift */; }; + B4A0C69370E6008A971463E7 /* BugReportScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C89820BB2B88D4EA28131C /* BugReportScreenViewModelProtocol.swift */; }; + B4AAB3257A83B73F53FB2689 /* StateStoreViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */; }; + B5321A1F5B26A0F3EC54909E /* CollapsibleFlowLayoutTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC5F5209279A752D98AAC4B2 /* CollapsibleFlowLayoutTests.swift */; }; + B5479997ECC516C121E6625E /* LocationMarkerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFECCE59967018204876D0A5 /* LocationMarkerView.swift */; }; + B5618E3C948584E5C1F67033 /* DTHTMLElement+AttributedStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E508AB0EDEE017FF4F6F8D1 /* DTHTMLElement+AttributedStringBuilder.swift */; }; + B5899F18AD6C56CE08FE532B /* RoomSummaryProviderMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC83F47D2173B7538AA72E0E /* RoomSummaryProviderMock.swift */; }; + B5E455C9689EA600EDB3E9E0 /* NavigationRootCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA28F29C9F93E93CC3C2C715 /* NavigationRootCoordinator.swift */; }; + B6048166B4AA4CEFEA9B77A6 /* InfoPlistReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A580295A56B55A856CC4084 /* InfoPlistReader.swift */; }; + B6064D82FCDCB829601C1F59 /* SecureBackupLogoutConfirmationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FEE10AB666891E6A675E5E /* SecureBackupLogoutConfirmationScreen.swift */; }; + B659E3A49889E749E3239EA7 /* MockMediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FD6E621CC5E6D4830D96D2D /* MockMediaProvider.swift */; }; + B6DA66EFC13A90846B625836 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 91DE43B8815918E590912DDA /* InfoPlist.strings */; }; + B6DF6B6FA8734B70F9BF261E /* BlurHashDecode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5272BC4A60B6AD7553BACA1 /* BlurHashDecode.swift */; }; + B6EC2148FA5443C9289BEEBA /* MediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */; }; + B721125D17A0BA86794F29FB /* MockServerSelectionScreenState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E057FB1F07A5C201C89061 /* MockServerSelectionScreenState.swift */; }; + B773ACD8881DB18E876D950C /* WaveformSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94028A227645FA880B966211 /* WaveformSource.swift */; }; + B7888FC1E1DEF816D175C8D6 /* SecureBackupKeyBackupScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD72A9B720D75DBE60AC299F /* SecureBackupKeyBackupScreenModels.swift */; }; + B796A25F282C0A340D1B9C12 /* ImageRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2B5EDCD05D50BA9B815C66C /* ImageRoomTimelineItemContent.swift */; }; + B79E8AB83EBBDCD476D0362F /* PollFormScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = D622EC7898469BB1D0881CDD /* PollFormScreen.swift */; }; + B7C9E07F4F9CCC8DD7156A20 /* CallScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28146817C61423CACCF942F5 /* CallScreenModels.swift */; }; + 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 */; }; + 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 */; }; + B98A20A093A4FB785BFCCA53 /* BugReportScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3FBD9C2B9A5479526920399 /* BugReportScreenCoordinator.swift */; }; + B9A8C34A00D03094C0CF56F3 /* MediaUploadPreviewScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03FABD73FD8086EFAB699F42 /* MediaUploadPreviewScreenViewModelTests.swift */; }; + 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 */; }; + 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 */; }; + BB6BF528BC7F5B87E08C4F18 /* CameraPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8A3B7637DDBD6AA97AC2545 /* CameraPicker.swift */; }; + BB784A02BADB03C820617A46 /* TextRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90A55430639712CFACA34F43 /* TextRoomTimelineItem.swift */; }; + BB9B800C6094E34860E89DC5 /* AppLockSetupBiometricsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8CCF9A924521DECA44778C4 /* AppLockSetupBiometricsScreen.swift */; }; + BC7CA1379D7C24F47B1B8B7E /* PaginationIndicatorRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E7F7A975514E850A834B29F /* PaginationIndicatorRoomTimelineView.swift */; }; + BCC864190651B3A3CF51E4DF /* MediaFileHandleProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEC1D382565A4E9CAC2F14EA /* MediaFileHandleProxy.swift */; }; + BD0BE20DBCE31253AE4490A1 /* RoomListFiltersEmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC1DDB2293A51EA4C2739351 /* RoomListFiltersEmptyStateView.swift */; }; + BD11E639CF566A9DA8FCA717 /* RoundedLabelItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE7C80EF77AD102053D3646E /* RoundedLabelItem.swift */; }; + BD6685592716CA957D7BAAC4 /* RoomChangeRolesScreenSelectedItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D9B45D584D232CB9E5C7734 /* RoomChangeRolesScreenSelectedItem.swift */; }; + BD782053BE4C3D2F0BDE5699 /* ServiceLocator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57F95CADD0A5DBD76B990FCB /* ServiceLocator.swift */; }; + 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 */; }; + 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 */; }; + 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 */; }; + C11939FDC40716C4387275A4 /* NotificationSettingsEditScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8544F7058D31DBEB8DBFF0F5 /* NotificationSettingsEditScreenViewModelTests.swift */; }; + C13128AAA787A4C2CBE4EE82 /* MessageForwardingScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC10CCC8D68B863E20660DBC /* MessageForwardingScreenViewModelProtocol.swift */; }; + C1429699A6A5BB09A25775C1 /* AudioPlayerStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89233612A8632AD7E2803620 /* AudioPlayerStateTests.swift */; }; + C1910A16BDF131FECA77BE22 /* EmojiPickerScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEA38B9851CFCC4D67F5587D /* EmojiPickerScreenCoordinator.swift */; }; + C1A5C386319835FB0C77736B /* ReportContentScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A16CD2C62CB7DB78A4238485 /* ReportContentScreenCoordinator.swift */; }; + C1D0AB8222D7BAFC9AF9C8C0 /* MapLibreMapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 622D09D4ECE759189009AEAF /* MapLibreMapView.swift */; }; + C26DB49C06C00B5DF1A991A5 /* InviteUsersScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1454CF3AABD242F55C8A2615 /* InviteUsersScreenModels.swift */; }; + C2879369106A419A5071F1F8 /* VoiceMessageRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B0A96B8FE4849227945067 /* VoiceMessageRecorder.swift */; }; + C32765D740C81AD4C42E8F50 /* CreateRoomFlowParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 935C2FB18EFB8EEE96B26330 /* CreateRoomFlowParameters.swift */; }; + C3317EF833AB4060988DF098 /* SAS.strings in Resources */ = {isa = PBXBuildFile; fileRef = 135FC689EA39AE1D34153B58 /* SAS.strings */; }; + C3522917C0C367C403429EEC /* CoordinatorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B251F5B4511D1CA0BA8361FE /* CoordinatorProtocol.swift */; }; + C3BB6887CF13B19182E81F87 /* IdentityConfirmationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A03E073077D92AA19C43DCF /* IdentityConfirmationScreenCoordinator.swift */; }; + C405528EB4BBEA93579050EE /* VoiceMessageRecordingButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46A2AD86F7E618F468F6FAF5 /* VoiceMessageRecordingButton.swift */; }; + C4078364FD9FA00EA9D00A15 /* RoomMembersListScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45CDF9A107BFE6C79B58D6B5 /* RoomMembersListScreenViewModelProtocol.swift */; }; + C413D36D44F89DE63D3ADFA4 /* ReportContentScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = A433BE28B40D418237BE37B5 /* ReportContentScreen.swift */; }; + C4180F418235DAD9DD173951 /* TemplateScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9873076F224E4CE09D8BD47D /* TemplateScreenUITests.swift */; }; + C49FCC766673006B6D299F1C /* RoomDetailsEditScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DF8F7A3AD83D04C08D75E01 /* RoomDetailsEditScreenViewModelProtocol.swift */; }; + C4D2BCAA54E2C62B94B24AF4 /* InviteUsersScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2E9B841EE4878283ECDB554 /* InviteUsersScreen.swift */; }; + C4E0D03DF88242697545A9B7 /* UserIndicatorController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD1275D9CE0FFBA6E8E85426 /* UserIndicatorController.swift */; }; + C4F69156C31A447FEFF2A47C /* DTHTMLElement+AttributedStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E508AB0EDEE017FF4F6F8D1 /* DTHTMLElement+AttributedStringBuilder.swift */; }; + C4FE0E11A907C8999F92D5A8 /* TimelineStartRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F5F9E02B1AB5350B1815E7 /* TimelineStartRoomTimelineItem.swift */; }; + C55A44C99F64A479ABA85B46 /* RoomScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5221DFDF809142A2D6AC82B9 /* RoomScreen.swift */; }; + C5627BCC3EBBB96A943B6D93 /* RestorationTokenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7978C9EFBDD7DE39BD86726 /* RestorationTokenTests.swift */; }; + C58E305C380D3ADDF7912180 /* StickerRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 818695BED971753243FEF897 /* StickerRoomTimelineItem.swift */; }; + C5A07E2D88BE7D51DCECD166 /* LoginScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D0B159AFFBBD8ECFD0E37FA /* LoginScreenModels.swift */; }; + C67FCC854F3A6FC7A2EC04D0 /* MediaUploadPreviewScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70C86696AC9521F8ED88FBEB /* MediaUploadPreviewScreen.swift */; }; + C6C06DDA8881260303FBA3A0 /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2141693488CE5446BB391964 /* Date.swift */; }; + C76892321558E75101E68ED6 /* ReadableFrameModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398817652FA8ABAE0A31AC6D /* ReadableFrameModifier.swift */; }; + C7774720A4B2E34693E3227C /* RoomNotificationSettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8896CDD20CA2D87EA3B848A1 /* RoomNotificationSettingsScreen.swift */; }; + C7ABEBECDC513F7887DACF66 /* ProgressMaskModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68010886142843705E342645 /* ProgressMaskModifier.swift */; }; + 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 */; }; + C8BD80891BAD688EF2C15CDB /* MediaUploadPreviewScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74DD0855F2F76D47E5555082 /* MediaUploadPreviewScreenCoordinator.swift */; }; + C8C7AF33AADF88B306CD2695 /* QRCodeLoginService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4427AF4B7FB7EF3E3D424C7 /* QRCodeLoginService.swift */; }; + C8E0FA0FF2CD6613264FA6B9 /* MessageForwardingScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFEA446F8618DBA79A9239CC /* MessageForwardingScreen.swift */; }; + C915347779B3C7FDD073A87A /* AVMetadataMachineReadableCodeObjectExtensionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93E1FF0DFBB3768F79FDBF6D /* AVMetadataMachineReadableCodeObjectExtensionsTest.swift */; }; + C97325EFDCCEE457432A9E82 /* MessageText.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E0B4A34E69BD2132BEC521 /* MessageText.swift */; }; + 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 */; }; + C9F5B48D15B9BCAE1F8D564E /* RoomNotificationModeProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1511766C534367700C8DD75 /* RoomNotificationModeProxy.swift */; }; + CA12AE0DCD57D49CD96C699A /* WaveformCursorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB9EABCA9348DFA27439A809 /* WaveformCursorView.swift */; }; + CB137BFB3E083C33E398A6CB /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 020597E28A4BC8E1BE8EDF6E /* KeychainAccess */; }; + CB498F4E27AA0545DCEF0F6F /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 36B7FC232711031AA2B0D188 /* DTCoreText */; }; + CB6956565D858C523E3E3B16 /* ComposerDraftServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7E37072597F67C4DD8CC2DB /* ComposerDraftServiceProtocol.swift */; }; + CB6BCBF28E4B76EA08C2926D /* StateRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B16048D30F0438731C41F775 /* StateRoomTimelineItem.swift */; }; + CB99B0FA38A4AC596F38CC13 /* KeychainControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5E94DCFEE803E5ABAE8ACCE /* KeychainControllerProtocol.swift */; }; + 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 */; }; + CC961529F9F1854BEC3272C9 /* LayoutMocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC8AA23D4F37CC26564F63C5 /* LayoutMocks.swift */; }; + CCBEC2100CAF2EEBE9DB4156 /* TemplateScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA40B98B098B6F0371B750B3 /* TemplateScreenModels.swift */; }; + CD0088B763CD970CF1CBF8CB /* DateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B5E97E9615A158C76B2AB77 /* DateTests.swift */; }; + CD6A72B65D3B6076F4045C30 /* PHGPostHogConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6B891A6DA826E2461DBB40F /* PHGPostHogConfiguration.swift */; }; + CDAE3A37D4DF136F9D07DB61 /* RoomChangeRolesScreenSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF710CB1C31F8938EAA3A7D /* RoomChangeRolesScreenSection.swift */; }; + CDCA8A559E098503DDE29477 /* AttributedStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5C6FBF97B6EED3D4FA5EFF /* AttributedStringBuilder.swift */; }; + CE1694C7BB93C3311524EF28 /* Untranslated.strings in Resources */ = {isa = PBXBuildFile; fileRef = D2F7194F440375338F8E2487 /* Untranslated.strings */; }; + CE3B7FC34FB2C279AAA5EA01 /* AVMetadataMachineReadableCodeObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3339B1DDB1341E833D2555BC /* AVMetadataMachineReadableCodeObject.swift */; }; + CE6F237360875D3D573FD0B2 /* RoomNotificationSettingsProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD6B522BD637845AB9570B10 /* RoomNotificationSettingsProxy.swift */; }; + CE9530A4CA661E090635C2F2 /* NotificationItemProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */; }; + CEAEA57B7665C8E790599A78 /* BlockedUsersScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 240610DF32F3213BEC5611D7 /* BlockedUsersScreenViewModelTests.swift */; }; + CEB8FB1269DE20536608B957 /* LoginMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B41FABA2B0AEF4389986495 /* LoginMode.swift */; }; + CF38B70D8C6DD42C00A56A27 /* LogViewerScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A84D413BF49F0E980F010A6B /* LogViewerScreenCoordinator.swift */; }; + CF4044A8EED5C41BC0ED6ABE /* SoftLogoutScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D316BB02636AF2174F2580E6 /* SoftLogoutScreenViewModelProtocol.swift */; }; + CFEC53440C572CEEABC4A6A0 /* ElementXAttributeScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = C024C151639C4E1B91FCC68B /* ElementXAttributeScope.swift */; }; + 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 */; }; + 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 */; }; + D2825E013A8ECFB66D9A1DE6 /* RoomChangeRolesScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F841F219ACDFC1D3F42FEFB /* RoomChangeRolesScreenViewModelTests.swift */; }; + D29E046C1E3045E0346C479D /* RoomRolesAndPermissionsUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45571C2EBD98ED7E0CEA7AF7 /* RoomRolesAndPermissionsUITests.swift */; }; + D2D70B5DB1A5E4AF0CD88330 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 033DB41C51865A2E83174E87 /* target.yml */; }; + D33AC79A50DFC26D2498DD28 /* FileRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5098DA7799946A61E34A2373 /* FileRoomTimelineItem.swift */; }; + D34E328E9E65904358248FDD /* GlobalSearchScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436A0D98D372B17EAE9AA999 /* GlobalSearchScreenModels.swift */; }; + D3FD96913D2B1AAA3149DAC7 /* CreateRoomViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69D42EE0102D2857933625DD /* CreateRoomViewModelTests.swift */; }; + D415764645491F10344FC6AC /* Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60F18AECC9D38C2B6D85F99C /* Publisher.swift */; }; + D43F0503EF2CBC55272538FE /* SDKGeneratedMocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2F079B5DBD0D85FEA687AAE /* SDKGeneratedMocks.swift */; }; + D46C33F8B61B55F0C8C2D15F /* LocationRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B2AC540DE619B36832A5DB5 /* LocationRoomTimelineItem.swift */; }; + D4CB979EB4FE26AAD9F9A72B /* UserProfileScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 604A69C081B935D6A38DE6D8 /* UserProfileScreenModels.swift */; }; + D4D5595C4A2A702CFF4E94FF /* HeroImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EC2F1622C5BBABED6012E12 /* HeroImage.swift */; }; + D4D7CCECC6C0AAFC42E165BB /* NotificationPermissionsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9BBB18FB27F09032AD8769 /* NotificationPermissionsScreenViewModel.swift */; }; + D53B80EF02C1062E68659EDD /* ReportContentViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086C19086DD16E9B38E25954 /* ReportContentViewModelTests.swift */; }; + D55AF9B5B55FEED04771A461 /* RoomFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A008E57D52B07B78DFAD1BB /* RoomFlowCoordinator.swift */; }; + D5681C80D8281560AACE0035 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045253F9967A535EE5B16691 /* Label.swift */; }; + D5B1531A72387D432939D4E0 /* RoomDirectorySearchProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0516C69708D5CBDE1A8E77EC /* RoomDirectorySearchProxyProtocol.swift */; }; + D5C805F49B2C75DC3793E780 /* EmojiItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37A243E04B58DC6E41FDCD82 /* EmojiItem.swift */; }; + D5E771132BB36240DE38102F /* RoomMessageEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80E815FF3CC5E5A355E3A25E /* RoomMessageEventStringBuilder.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 */; }; + D6661A94DBD97658B2ADBD6A /* MapTilerStaticMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A4D29F2683F5772AC72406F /* MapTilerStaticMap.swift */; }; + 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 */; }; + 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 */; }; + 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 */; }; + DC08ADC41E792086A340A8B3 /* AccessibilityIdentifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */; }; + DC68E866D6E664B0D2B06E74 /* MockImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC1DA29A5A041CC0BACA7CB0 /* MockImageCache.swift */; }; + DC77E9DB2CFBE84A2BDF20C5 /* RoomRolesAndPermissionsFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0833F51229E166BCA141D004 /* RoomRolesAndPermissionsFlowCoordinator.swift */; }; + DCFE7CB3B9A104330BBB96AD /* AnalyticsPromptScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B67DF223EEB8DCAF178A1D4 /* AnalyticsPromptScreenCoordinator.swift */; }; + DDB47D29C6865669288BF87C /* UIFont+AttributedStringBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = E8CA187FE656EE5A3F6C7DE5 /* UIFont+AttributedStringBuilder.m */; }; + DDE7B4771452300C103B1EB8 /* RoomDirectoryCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F6210134203BE1F2DD5C679 /* RoomDirectoryCell.swift */; }; + DDFBDEE1DC32BDD5488F898C /* ClientProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F96CCBEAAA7F2185BFA354 /* ClientProxyMock.swift */; }; + DE4F8C4E0F1DB4832F09DE97 /* HomeScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31D6764D6976D235926FE5FC /* HomeScreenViewModel.swift */; }; + 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 */; }; + 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 */; }; + DFD5AA8688A34C72D48AF3B1 /* StaticLocationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5311C989EC15B4C2D699025 /* StaticLocationScreenViewModel.swift */; }; + DFF7D6A6C26DDD40D00AE579 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = F012CB5EE3F2B67359F6CC52 /* target.yml */; }; + E0B6A569AC3E81D233B43D60 /* SettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E625B0EB2F86B37C14EF7E6 /* SettingsScreenViewModel.swift */; }; + E0C167D41A48EDB30B447DE3 /* VoiceMessageRecordingComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73A5C3F7C9C1DA10CAEC6A98 /* VoiceMessageRecordingComposer.swift */; }; + 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 */; }; + 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 */; }; + E290C78E7F09F47FD2662986 /* Task.swift in Sources */ = {isa = PBXBuildFile; fileRef = A40C19719687984FD9478FBE /* Task.swift */; }; + E2D57361B835E4D2230960E6 /* ImageRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5599255A6C98EBDA77B76E6 /* ImageRoomTimelineView.swift */; }; + E2DB696117BAEABAD5718023 /* MediaSourceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49B9785E3AD7D1C15A29F2F /* MediaSourceProxy.swift */; }; + E2DDA49BD62F03F180A42E30 /* MapLibreStaticMapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 592A35163B0749C66BFD6186 /* MapLibreStaticMapView.swift */; }; + E313BDD2B8813144139B2E00 /* UserDiscoveryServiceTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0287793F11C480E242B03DF5 /* UserDiscoveryServiceTest.swift */; }; + E3291AD16D7A5CB14781819C /* UserNotificationCenterProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45D8149FDDA0315CDC553B4B /* UserNotificationCenterProtocol.swift */; }; + E32A18802EB37EEE3EF7B965 /* GlobalSearchScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B788615712FED326F73D3F83 /* GlobalSearchScreenViewModelProtocol.swift */; }; + E362924A42934C9F0F97A956 /* OIDCConfigurationProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = A69869844D2B6F5BD9AABF85 /* OIDCConfigurationProxy.swift */; }; + E37044401D9951D6C02C0855 /* TracingConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED003DF1B7CF40E7073A2280 /* TracingConfiguration.swift */; }; + E3AC72E3E58F364EF15C1CC7 /* NotificationSettingsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 514363244AE7D68080D44C6F /* NotificationSettingsScreenViewModelTests.swift */; }; + E3CA565A4B9704F191B191F0 /* JoinedRoomSize+MemberCount.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBF9AEA706926DD0DA2B954C /* JoinedRoomSize+MemberCount.swift */; }; + E3E1E255DC8CB34BD8573E0D /* UserIndicatorControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A12D3B1BCF920880CA8BBB6B /* UserIndicatorControllerProtocol.swift */; }; + E45C9FA22BC13B477FD3B4AC /* EmojiDetection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D99730313BEBF08CDE81EE3 /* EmojiDetection.swift */; }; + E468CC731C3F4D678499E52F /* LAContextMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BA5A62DA4B543827FF82354 /* LAContextMock.swift */; }; + E481C8FDCB6C089963C95344 /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = BC01130651CB23340B899032 /* DeviceKit */; }; + E49F74BD93230BDEFFE5EA51 /* RoomNotificationSettingsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D295F0081084F38DB20893 /* RoomNotificationSettingsScreenViewModelTests.swift */; }; + E4B07FF075C99D04D9AF792D /* AppLockSetupPINScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B410B32B72C90BF94E481F33 /* AppLockSetupPINScreenModels.swift */; }; + E4F924DECC66389C1C810550 /* AuthenticationStartScreenBackgroundImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50D685B4DB38BB5BD87C956A /* AuthenticationStartScreenBackgroundImage.swift */; }; + E58F1F3276E98A93F7D39219 /* RoomPollsHistoryScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1D8479BB704B7EF696F8ABE /* RoomPollsHistoryScreenCoordinator.swift */; }; + E5AB28123E2488F97E953AC0 /* CallNotificationRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1ED17433ADC77287F8904F9 /* CallNotificationRoomTimelineItem.swift */; }; + E5F4C992845388B50BABACAA /* ServerSelectionScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8BC4C791D0E88CFCF4E5DF /* ServerSelectionScreenCoordinator.swift */; }; + 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 */; }; + E79B247A6DD28759636317EA /* AuthenticationStartScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C3ACC093F88FD9888518561 /* AuthenticationStartScreenViewModel.swift */; }; + E79D79CDAFE8BEBCC3AECA54 /* AppLockScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08283301736A6FE9D558B2CB /* AppLockScreenViewModelProtocol.swift */; }; + 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 */; }; + E9347F56CF0683208F4D9249 /* RoomNotificationSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81A9B5225D0881CEFA2CF7C9 /* RoomNotificationSettingsScreenViewModel.swift */; }; + E9560744F7B0292E20ECE5F2 /* RoomDetailsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63E8A1E8EE094F570573B6E8 /* RoomDetailsScreenViewModelProtocol.swift */; }; + E96005321849DBD7C72A28F2 /* UITestsAppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46C208DA43CE25D13E670F40 /* UITestsAppCoordinator.swift */; }; + E9D2ED1C4186931E3D5FDA4E /* QRCodeLoginScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 718D8767035D37E2DB5CC550 /* QRCodeLoginScreenViewModelProtocol.swift */; }; + EA01A06EEDFEF4AE7652E5F3 /* NSRegularExpresion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95BAC0F6C9644336E9567EE6 /* NSRegularExpresion.swift */; }; + EA6613B29BA671F39CE1B1D2 /* ConfirmationDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = B383DCD3DCB19E00FD478A5F /* ConfirmationDialog.swift */; }; + EA78A7512AFB1E5451744EB1 /* AppRouteURLParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E461B3C8BBBFCA400B268D14 /* AppRouteURLParserTests.swift */; }; + EA974337FA7D040E7C74FE6E /* RoomDetailsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EFE1922F39398ABFB36DF3F /* RoomDetailsViewModelTests.swift */; }; + EAB3C1F0BC7F671ED8BDF82D /* CompletionSuggestionServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ECF11669EF253E98AA2977A /* CompletionSuggestionServiceProtocol.swift */; }; + EAC6FE2CD4F50A43068ADCD8 /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 9573B94B1C86C6DF751AF3FD /* SwiftState */; }; + EAF2B3E6C6AEC4AD3A8BD454 /* RoomMemberDetailsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A87D0471D438A233C2CF4A /* RoomMemberDetailsScreenViewModel.swift */; }; + EB87DF90CF6F8D5D12404C6E /* SecureBackupLogoutConfirmationScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848F69921527D31CAACB93AF /* SecureBackupLogoutConfirmationScreenViewModelTests.swift */; }; + EB88DBD77221E2CFE463018C /* NSE.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 0D8F620C8B314840D8602E3F /* NSE.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + EB9F4688006B52E69DF5358F /* BlankFormCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7F63EB1525E697CAEB002B /* BlankFormCoordinator.swift */; }; + EBE13FAB4E29738AC41BD3E5 /* InfoPlistReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A580295A56B55A856CC4084 /* InfoPlistReader.swift */; }; + EC280623A42904341363EAAF /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = A20EA00CCB9DBE0FFB17DD09 /* Collections */; }; + EC3320639828BED8B3E5F2C6 /* EncryptionResetScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5875F7C0A2398E9F134B1284 /* EncryptionResetScreenViewModel.swift */; }; + ED3E91E6166E4923791ACA84 /* ResolveVerifiedUserSendFailureScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56852036214ABA9D7D305768 /* ResolveVerifiedUserSendFailureScreenViewModelProtocol.swift */; }; + ED564C8C7C43CF5F67000368 /* PlatformViewVersionPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D26813CCE39221FE30BF22CD /* PlatformViewVersionPredicate.swift */; }; + ED635D7F00FA07E94D3CE1E8 /* PreviewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9B796D347E53631576F631C /* PreviewTests.swift */; }; + ED90A59F068FD0CA27E602ED /* UserProfileListRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = E10DA51DBC8C7E1460DBCCBD /* UserProfileListRow.swift */; }; + EDF8919F15DE0FF00EF99E70 /* DocumentPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F5567A7EF6F2AB9473236F6 /* DocumentPicker.swift */; }; + EE4E2C1922BBF5169E213555 /* PillAttachmentViewProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B53D6C5C0D14B04D3AB3F6E /* PillAttachmentViewProvider.swift */; }; + EE56238683BC3ECA9BA00684 /* GlobalSearchScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA4D639E27D5882A6A71AECF /* GlobalSearchScreenViewModelTests.swift */; }; + EE57A96130DD8DB053790AE2 /* EventTimelineItemSDKMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7A6BBC686B1F840FA807FB /* EventTimelineItemSDKMock.swift */; }; + EE8491AD81F47DF3C192497B /* DecorationTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 184CF8C196BE143AE226628D /* DecorationTimelineItemProtocol.swift */; }; + EEAE954289DE813A61656AE0 /* LayoutDirection.swift in Sources */ = {isa = PBXBuildFile; fileRef = C14D83B2B7CD5501A0089EFC /* LayoutDirection.swift */; }; + EEB9C1555C63B93CA9C372C2 /* EmojiPickerScreenHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B5E29E9A22F45534FBD5B58 /* EmojiPickerScreenHeaderView.swift */; }; + EEC40663922856C65D1E0DF5 /* KeychainControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDB9C37196A4C79F24CE80C6 /* KeychainControllerTests.swift */; }; + EF0D0155DD104C7A41A2EB0E /* PlainMentionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AE78FA0011E07920AE83135 /* PlainMentionBuilder.swift */; }; + EF47D802A404A53F15D5D4B6 /* JoinRoomScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD7C0A2750998C2D77AD00F /* JoinRoomScreenViewModel.swift */; }; + EF5009AC03212227131C8AF2 /* RoomNotificationSettingsProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E55B5EA766E89FF1F87C3ACB /* RoomNotificationSettingsProxyProtocol.swift */; }; + EF890DEF0479E66548F2BA23 /* AppLockTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 490BEADEFB2D6B7C9F618AE8 /* AppLockTimer.swift */; }; + EFBBD44C0A16F017C32D2099 /* TimelineItemStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72614BFF35B8394C6E13F55A /* TimelineItemStatusView.swift */; }; + F0570F1ECD70C4C851FB2052 /* SecureBackupRecoveryKeyScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93E7304F5ECB4CB11CB10E60 /* SecureBackupRecoveryKeyScreenViewModelProtocol.swift */; }; + F06CE9132855E81EBB6DDC32 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 940C605265DD82DA0C655E23 /* Kingfisher */; }; + F07D88421A9BC4D03D4A5055 /* VideoRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F348B5F2C12F9D4F4B4D3884 /* VideoRoomTimelineItem.swift */; }; + F08F7BC07CA9AEF5CD157918 /* Snapshotting.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF17EA323AD0205A6AB621AA /* Snapshotting.swift */; }; + F0A26CD502C3A5868353B0FA /* ServerConfirmationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24DEE0682C95F897B6C7CB0D /* ServerConfirmationScreenViewModel.swift */; }; + F0C2C49D707839F5273BFC6D /* WebRegistrationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C161B06F417CA5D1F1E088 /* WebRegistrationScreenModels.swift */; }; + F0DACC95F24128A54CD537E4 /* GlobalSearchScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24B8177BD2AF45A286F5DA31 /* GlobalSearchScreen.swift */; }; + F0F82C3C848C865C3098AA52 /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = 21C83087604B154AA30E9A8F /* SnapshotTesting */; }; + F103924DED414ADFE398CE99 /* RoomPollsHistoryScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A130A2251A15A7AACC84FD37 /* RoomPollsHistoryScreenViewModelProtocol.swift */; }; + 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 */; }; + F253AAB4C8F06208173C9C4A /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; }; + F2D5C0E1351DA7BD16867629 /* TimelineStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD4823EAB4B4E8BAB4F6B8C /* TimelineStyle.swift */; }; + F37629BAA5E8F50AAF2A131D /* SoftLogoutScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB7BAD55A4E2B8E5828CD64C /* SoftLogoutScreenViewModel.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 */; }; + 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 */; }; + F54E2D6CAD96E1AC15BC526F /* MessageForwardingScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E60332509665C00179ACF6 /* MessageForwardingScreenViewModel.swift */; }; + 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 */; }; + 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 */; }; + F6F49E37272AD7397CD29A01 /* HomeScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */; }; + F7567DD6635434E8C563BF85 /* AnalyticsClientProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3B97591B2D3D4D67553506D /* AnalyticsClientProtocol.swift */; }; + F777C6FEE7D106136E2ED2B2 /* MessageForwardingScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F6E6EDC4BBF962B2ED595A4 /* MessageForwardingScreenViewModelTests.swift */; }; + F78BAD28482A467287A9A5A3 /* EventBasedMessageTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0900BBF0A5D5D775E917C70 /* EventBasedMessageTimelineItemProtocol.swift */; }; + F7932A3F075B0D3F24DEECB5 /* VoiceMessagePreviewComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE807361805463F5AEDD1CA /* VoiceMessagePreviewComposer.swift */; }; + F7BC744FFA7FE248FAE7F570 /* UserIndicatorToastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F57C8022B8A871A1DCD1750A /* UserIndicatorToastView.swift */; }; + F7D709D7ECABE46641BB8B6B /* PHGPostHogProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEEAE1BFAACD6C96B6DB731 /* PHGPostHogProtocol.swift */; }; + F833D5B5BE6707F961FA88DB /* SecureBackupController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A1119E9C63AE530252640D2 /* SecureBackupController.swift */; }; + F86102DC2C68BBBB0521BAAE /* SoftLogoutScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BB385E148DE55C85C0A02D6 /* SoftLogoutScreenModels.swift */; }; + F8B2F5CBCF2A0E0798E8D646 /* TimelineViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB5B00A014307CE37B2812CD /* TimelineViewModelProtocol.swift */; }; + F8C87130FD999F7F1076208C /* RoomChangePermissionsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89AAEA70CFF3284920811941 /* RoomChangePermissionsScreen.swift */; }; + F8E725D42023ECA091349245 /* AudioRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57EAAF82432B0B53881CF826 /* AudioRoomTimelineItem.swift */; }; + F8F47CE757EE656905F01F2C /* RoomRolesAndPermissionsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90DFF217B3D9D0941283278C /* RoomRolesAndPermissionsScreenViewModelProtocol.swift */; }; + F9842667B68DC6FA1F9ECCBB /* NSItemProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72EFC8C634469F9262659C7 /* NSItemProvider.swift */; }; + F99FB21EFC6D99D247FE7CBE /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = DE8DC9B3FBA402117DC4C49F /* Kingfisher */; }; + F9EA79092C18A8CFE4922DD2 /* PollFormScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F64A8582F65567AC38C2976A /* PollFormScreenViewModel.swift */; }; + FA2BBAE9FC5E2E9F960C0980 /* NavigationCoordinators.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8F28602AC7AC881AED37EBA /* NavigationCoordinators.swift */; }; + FA5A7E32B1920FCB4EEDC1BA /* RoomDetailsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6493AC9979CEB1410302BFE3 /* RoomDetailsScreenCoordinator.swift */; }; + FA71CD334F2D2289BEF0D749 /* SecureBackupRecoveryKeyScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A2FCA3D0F239B9E911B966B /* SecureBackupRecoveryKeyScreen.swift */; }; + FA9C427FFB11B1AA2DCC5602 /* RoomProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */; }; + FB0A9D06FC9122E37992D962 /* LayoutDirection.swift in Sources */ = {isa = PBXBuildFile; fileRef = C14D83B2B7CD5501A0089EFC /* LayoutDirection.swift */; }; + FB53CD9B74A15B3B94F9F788 /* CreateRoomModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B849D2FF2CC12BA411A1651 /* CreateRoomModels.swift */; }; + FB595EC9C00AB32F39034055 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A37E2FACFD041CE466223CD /* SceneDelegate.swift */; }; + FBD402E3170EB1ED0D1AA672 /* EncryptionKeyProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2355398E4A55DA5A89128AD1 /* EncryptionKeyProvider.swift */; }; + FBF09B6C900415800DDF2A21 /* EmojiProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C113E0CB7E15E9765B1817A /* EmojiProvider.swift */; }; + FC10228E73323BDC09526F97 /* PostHog in Frameworks */ = {isa = PBXBuildFile; productRef = 4278261E147DB2DE5CFB7FC5 /* PostHog */; }; + FC8B95EC506E6BB5793D81CE /* ClientProtocolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E34685D186453E429ADEE58E /* ClientProtocolTests.swift */; }; + FCD3F2B82CAB29A07887A127 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 2B43F2AF7456567FE37270A7 /* KeychainAccess */; }; + FCDA202B246F75BA28E10C5F /* MapTilerAuthorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = E062C1750EFC8627DE4CAB8E /* MapTilerAuthorization.swift */; }; + FD29471C72872F8B7580E3E1 /* KeychainControllerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39C0D861FC397AC34BCF089E /* KeychainControllerMock.swift */; }; + FD4C21F8DA1E273DE94FCD1A /* NotificationItemProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B927CF5EF7FCCDA5EDC474B /* NotificationItemProxyProtocol.swift */; }; + FD4DEC88210F35C35B2FB386 /* ProcessInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3A1398EFF65090FDA1CB639 /* ProcessInfo.swift */; }; + FD762761C5D0C30E6255C3D8 /* ServerConfirmationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABA4CF2F5B4F68D02E412004 /* ServerConfirmationScreenViewModelProtocol.swift */; }; + FDD5B4B616D9FF4DE3E9A418 /* QRCodeScannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92DB574F954CC2B40F7BE892 /* QRCodeScannerView.swift */; }; + FE4593FC2A02AAF92E089565 /* ElementAnimations.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF1593DD87F974F8509BB619 /* ElementAnimations.swift */; }; + FEC03105D1BDE0F49BD7F243 /* PinnedEventsTimelineScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B6572E6EF5D5F4B0C338A40 /* PinnedEventsTimelineScreenModels.swift */; }; + FEFD5290B31FCBA6999912C8 /* RoomChangePermissionsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2721D7B051F0159AA919DA05 /* RoomChangePermissionsScreenViewModelProtocol.swift */; }; + FF34BF2AF731340AF9414A18 /* SwipeRightAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4552D3466B1453F287223ADA /* SwipeRightAction.swift */; }; + FF7E8ECC8E7E1D1851517536 /* PollFormScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 347D708104CCEF771428C9A3 /* PollFormScreenViewModelTests.swift */; }; + FF9C06BBF6AC6F1CFFBEBFFC /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 90791B9C739C716A40E1B230 /* target.yml */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 4448BD77D7203616C4FAD26A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = AC22997D58D612146053154D /* Project object */; + proxyType = 1; + remoteGlobalIDString = C0FAEB81CFD9776CD78CE489; + remoteInfo = ElementX; + }; + 4D8DD8FE84794CA168A8499A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = AC22997D58D612146053154D /* Project object */; + proxyType = 1; + remoteGlobalIDString = C0FAEB81CFD9776CD78CE489; + remoteInfo = ElementX; + }; + 6848AF4480814C5F810FB7EB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = AC22997D58D612146053154D /* Project object */; + proxyType = 1; + remoteGlobalIDString = C0FAEB81CFD9776CD78CE489; + remoteInfo = ElementX; + }; + 889C131F86E6415074D382B9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = AC22997D58D612146053154D /* Project object */; + proxyType = 1; + remoteGlobalIDString = C0FAEB81CFD9776CD78CE489; + remoteInfo = ElementX; + }; + AE0C21E7E01A23610E54DF9D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = AC22997D58D612146053154D /* Project object */; + proxyType = 1; + remoteGlobalIDString = FEB53A5BC378C913769656D8; + remoteInfo = NSE; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8E3CD0D0BB6697512E867C1D /* Embed Foundation Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + EB88DBD77221E2CFE463018C /* NSE.appex in Embed Foundation Extensions */, + ); + name = "Embed Foundation Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 00245D40CD90FD71D6A05239 /* EmojiPickerScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreen.swift; sourceTree = ""; }; + 00AFC5F08734C2EA4EE79C59 /* IdentityConfirmationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreen.swift; sourceTree = ""; }; + 00E5B2CBEF8F96424F095508 /* RoomDetailsEditScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenViewModelTests.swift; sourceTree = ""; }; + 012A284622B32052015F1F89 /* ReadMarkerRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadMarkerRoomTimelineView.swift; sourceTree = ""; }; + 01B795AAAB7B8747FE2FF311 /* LogViewerScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewerScreenModels.swift; sourceTree = ""; }; + 01C4C7DB37597D7D8379511A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 022E6BD64CB4610B9C95FC02 /* UserDetailsEditScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDetailsEditScreenViewModel.swift; sourceTree = ""; }; + 024F7398C5FC12586FB10E9D /* EffectsScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EffectsScene.swift; sourceTree = ""; }; + 0287793F11C480E242B03DF5 /* UserDiscoveryServiceTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDiscoveryServiceTest.swift; sourceTree = ""; }; + 029D5701F80A9AF7167BB4D0 /* TimelineModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineModels.swift; sourceTree = ""; }; + 02D155E09BF961BBA8F85263 /* InviteUsersScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenViewModel.swift; sourceTree = ""; }; + 02EE0FABA8ED6D6C1D6CE71D /* ReactionsSummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionsSummaryView.swift; sourceTree = ""; }; + 03277E40D0E0DE0712021A71 /* ServerConfirmationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenCoordinator.swift; sourceTree = ""; }; + 033DB41C51865A2E83174E87 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; + 035177BCD8E8308B098AC3C2 /* WindowManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowManager.swift; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + 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 = ""; }; + 052B2F924572AFD70B5F500E /* StartChatScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatScreenViewModel.swift; sourceTree = ""; }; + 054F469E433864CC6FE6EE8E /* ServerSelectionUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionUITests.swift; sourceTree = ""; }; + 05512FB13987D221B7205DE0 /* HomeScreenRecoveryKeyConfirmationBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenRecoveryKeyConfirmationBanner.swift; sourceTree = ""; }; + 05596E4A11A8C9346E9E54AE /* SoftLogoutScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutScreenCoordinator.swift; 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 = ""; }; + 0685156EB62D7E243F097CFC /* ServerSelectionScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionScreenViewModelProtocol.swift; sourceTree = ""; }; + 06B098A612DCB5A7358EECD5 /* DeveloperOptionsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenModels.swift; sourceTree = ""; }; + 06F27F588F9059128E17C669 /* WindowManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowManagerProtocol.swift; sourceTree = ""; }; + 06FAE373A7F20780BA84B59C /* MessageForwardingScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageForwardingScreenCoordinator.swift; sourceTree = ""; }; + 0724EBDFE8BB4C9E5547C57D /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = ""; }; + 07579F9C29001E40715F3014 /* NotificationSettingsChatType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsChatType.swift; sourceTree = ""; }; + 077D7C3BE199B6E5DDEC07EC /* AppCoordinatorStateMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCoordinatorStateMachine.swift; sourceTree = ""; }; + 07C6B0B087FE6601C3F77816 /* JoinedRoomProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinedRoomProxy.swift; sourceTree = ""; }; + 0825EAFD47332DD459DE893F /* SessionDirectoriesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionDirectoriesTests.swift; sourceTree = ""; }; + 08283301736A6FE9D558B2CB /* AppLockScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockScreenViewModelProtocol.swift; sourceTree = ""; }; + 0833F51229E166BCA141D004 /* RoomRolesAndPermissionsFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomRolesAndPermissionsFlowCoordinator.swift; sourceTree = ""; }; + 086B997409328F091EBA43CE /* RoomScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenUITests.swift; sourceTree = ""; }; + 086C19086DD16E9B38E25954 /* ReportContentViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentViewModelTests.swift; sourceTree = ""; }; + 095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProviderProtocol.swift; sourceTree = ""; }; + 099F2D36C141D845A445B1E6 /* EmojiProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiProviderTests.swift; sourceTree = ""; }; + 0A3E77399BD262D301451BF2 /* RoomDetailsEditScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenCoordinator.swift; sourceTree = ""; }; + 0A459AE4B6566B2FA99E86B2 /* TimelineItemBubbledStylerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemBubbledStylerView.swift; sourceTree = ""; }; + 0B0E0B55E2EE75AF67029924 /* SwipeToReplyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeToReplyView.swift; sourceTree = ""; }; + 0B32BBA8887BD7A5C4ECF16F /* RoomModerationRole.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomModerationRole.swift; sourceTree = ""; }; + 0B987FC3FDBAA0E1C5AA235C /* PaginationIndicatorRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationIndicatorRoomTimelineItem.swift; sourceTree = ""; }; + 0BB05221D7D941CC82DC8480 /* LogViewerScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewerScreenViewModel.swift; sourceTree = ""; }; + 0BCE3FAF40932AC7C7639AC4 /* AnalyticsSettingsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenViewModel.swift; sourceTree = ""; }; + 0BD116096CAA9139B95EEA9C /* UserProfileScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileScreenViewModel.swift; sourceTree = ""; }; + 0C34667458773B02AB5FB0B2 /* LegalInformationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreenViewModel.swift; sourceTree = ""; }; + 0C62E07C1164F5120727A2A8 /* AppLockSetupBiometricsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreenCoordinator.swift; sourceTree = ""; }; + 0CB569EAA5017B5B23970655 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Localizable.strings; sourceTree = ""; }; + 0CCC6C31102E1D8B9106DEDE /* AppLockSetupBiometricsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreenViewModelProtocol.swift; sourceTree = ""; }; + 0D0B159AFFBBD8ECFD0E37FA /* LoginScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreenModels.swift; sourceTree = ""; }; + 0D879FC4E881E748BB9B34DC /* RoomChangePermissionsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangePermissionsScreenCoordinator.swift; sourceTree = ""; }; + 0D8F620C8B314840D8602E3F /* NSE.appex */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "wrapper.app-extension"; path = NSE.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 0DBB08A95EFA668F2CF27211 /* AppLockSetupFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupFlowCoordinator.swift; sourceTree = ""; }; + 0DF5CBAF69BDF5DF31C661E1 /* IntentionalMentions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentionalMentions.swift; sourceTree = ""; }; + 0E8BDC092D817B68CD9040C5 /* UserSessionStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionStore.swift; sourceTree = ""; }; + 0E95B3BDB80531C85CD50AE6 /* InvitedRoomProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitedRoomProxy.swift; sourceTree = ""; }; + 0EE9EAF0309A2A1D67D8FAF5 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = sv; path = sv.lproj/Localizable.stringsdict; sourceTree = ""; }; + 0F5567A7EF6F2AB9473236F6 /* DocumentPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentPicker.swift; sourceTree = ""; }; + 0F569CFB77E0D40BD82203D9 /* AuthenticationClientBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationClientBuilder.swift; sourceTree = ""; }; + 0F64447FF544298A6A3BEF85 /* NotificationSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenModels.swift; sourceTree = ""; }; + 0FA60F848D1C14F873F9621A /* RoomMemberDetailsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsScreenCoordinator.swift; sourceTree = ""; }; + 105429F29096729EDD3152CF /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/SAS.strings; sourceTree = ""; }; + 1059E2AE7878CF7820592637 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 105B2A8426404EF66F00CFDB /* RoomTimelineItemFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFactory.swift; sourceTree = ""; }; + 10CC626F97AD70FF0420C115 /* RoomSummaryProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProviderProtocol.swift; sourceTree = ""; }; + 10F130DF775CE6BC51A4E392 /* AppLockSetupBiometricsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreenModels.swift; sourceTree = ""; }; + 10F32E0B4B83D2A11EE8D011 /* InviteUsersScreenSelectedItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenSelectedItem.swift; sourceTree = ""; }; + 11151E78D6BB2B04A8FBD389 /* EmojiPickerScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenViewModelProtocol.swift; sourceTree = ""; }; + 111B698739E3410E2CDB7144 /* MXLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXLog.swift; sourceTree = ""; }; + 113356152C099951A6D17D85 /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/Localizable.strings; sourceTree = ""; }; + 1215A4FC53D2319E81AE8970 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 1222DB76B917EB8A55365BA5 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; + 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 = ""; }; + 130ED565A078F7E0B59D9D25 /* UNTextInputNotificationResponse+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNTextInputNotificationResponse+Creator.swift"; sourceTree = ""; }; + 136F80A613B55BDD071DCEA5 /* JoinRoomScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinRoomScreenModels.swift; sourceTree = ""; }; + 13802897C7AFA360EA74C0B0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = ""; }; + 13BE9781699FB510E9263192 /* AppSettingsHook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettingsHook.swift; sourceTree = ""; }; + 1423AB065857FA546444DB15 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = ""; }; + 1454CF3AABD242F55C8A2615 /* InviteUsersScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenModels.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 = ""; }; + 15A657D96779D1DEB8EF1327 /* CreateRoomViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomViewModel.swift; sourceTree = ""; }; + 161CD412E75F4086F422AE39 /* SessionVerificationScreenStateMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenStateMachine.swift; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + 18FE0CDF1FFA92EA7EE17B0B /* RoomTimelineControllerFactoryProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerFactoryProtocol.swift; sourceTree = ""; }; + 190EC7285D3CFEF0D3011BCF /* GeoURI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoURI.swift; sourceTree = ""; }; + 196004E7695FBA292A7944AF /* ScreenTrackerViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenTrackerViewModifier.swift; sourceTree = ""; }; + 1A02406480C351B8C6E0682C /* MediaLoaderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaLoaderProtocol.swift; sourceTree = ""; }; + 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Strings+Untranslated.swift"; sourceTree = ""; }; + 1A4D29F2683F5772AC72406F /* MapTilerStaticMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerStaticMap.swift; sourceTree = ""; }; + 1A7ED2EF5BDBAD2A7DBC4636 /* GeoURITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoURITests.swift; sourceTree = ""; }; + 1B065EC39C99C1303A101C1C /* WebRegistrationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebRegistrationScreen.swift; sourceTree = ""; }; + 1B2AC540DE619B36832A5DB5 /* LocationRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineItem.swift; sourceTree = ""; }; + 1B53D6C5C0D14B04D3AB3F6E /* PillAttachmentViewProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillAttachmentViewProvider.swift; sourceTree = ""; }; + 1B564D748B67A156F413CD97 /* NotificationSettingsEditScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsEditScreenModels.swift; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + 1C7A6BBC686B1F840FA807FB /* EventTimelineItemSDKMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventTimelineItemSDKMock.swift; sourceTree = ""; }; + 1C7F63EB1525E697CAEB002B /* BlankFormCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlankFormCoordinator.swift; sourceTree = ""; }; + 1CC575D1895FA62591451A93 /* RoomMemberDetailsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsScreen.swift; sourceTree = ""; }; + 1CD7C0A2750998C2D77AD00F /* JoinRoomScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinRoomScreenViewModel.swift; sourceTree = ""; }; + 1D56469A9EE0CFA2B7BA9760 /* SessionVerificationControllerProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationControllerProxyProtocol.swift; sourceTree = ""; }; + 1D652E78832289CD9EB64488 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/InfoPlist.strings; sourceTree = ""; }; + 1D67E616BCA82D8A1258D488 /* NetworkMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitor.swift; sourceTree = ""; }; + 1D70253004A5AEC9C73D6A4F /* ComposerDraftService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerDraftService.swift; sourceTree = ""; }; + 1D8C38663020DF2EB2D13F5E /* AppLockSetupSettingsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupSettingsScreenViewModel.swift; sourceTree = ""; }; + 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 = ""; }; + 1DB34B0C74CD242FED9DD069 /* LoginScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreenUITests.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 = ""; }; + 1E49D10BFA7E4D70A947888C /* DeactivateAccountScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeactivateAccountScreen.swift; sourceTree = ""; }; + 1E508AB0EDEE017FF4F6F8D1 /* DTHTMLElement+AttributedStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DTHTMLElement+AttributedStringBuilder.swift"; sourceTree = ""; }; + 1F2529D434C750ED78ADF1ED /* UserAgentBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAgentBuilder.swift; sourceTree = ""; }; + 1F7C6DDBB5D12F6EF6A3D6E1 /* CollapsibleReactionLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleReactionLayout.swift; sourceTree = ""; }; + 1FAF8C2226A57B9AB7446B31 /* AppLockSetupPINScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreenCoordinator.swift; sourceTree = ""; }; + 1FD51B4D5173F7FC886F5360 /* NoticeRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineItemContent.swift; sourceTree = ""; }; + 201305507D7DFD16E544563A /* EmojiLoaderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiLoaderProtocol.swift; sourceTree = ""; }; + 20872C3887F835958CE2F1D0 /* MapTilerStaticMapProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerStaticMapProtocol.swift; sourceTree = ""; }; + 20E69F67D2A70ABD08CA6D54 /* NotificationPermissionsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPermissionsScreenViewModelProtocol.swift; sourceTree = ""; }; + 2141693488CE5446BB391964 /* Date.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Date.swift; sourceTree = ""; }; + 216F0DDC98F2A2C162D09C28 /* FileRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileRoomTimelineItemContent.swift; sourceTree = ""; }; + 218AB05B4E3889731959C5F1 /* EventBasedTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBasedTimelineItemProtocol.swift; sourceTree = ""; }; + 21BA866267F84BF4350B0CB7 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "pt-BR"; path = "pt-BR.lproj/Localizable.stringsdict"; sourceTree = ""; }; + 21DD8599815136EFF5B73F38 /* UserFlowTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserFlowTests.swift; sourceTree = ""; }; + 225EFCA26877E75CDFE7F48D /* MapTilerStyleBuilderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerStyleBuilderProtocol.swift; sourceTree = ""; }; + 22730A30C50AC2E3D5BA8642 /* InviteUsersScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenViewModelProtocol.swift; sourceTree = ""; }; + 227AC5D71A4CE43512062243 /* URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URL.swift; sourceTree = ""; }; + 22DB19219E6CC4D002E15D48 /* GlobalSearchScreenCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchScreenCell.swift; sourceTree = ""; }; + 2355398E4A55DA5A89128AD1 /* EncryptionKeyProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionKeyProvider.swift; sourceTree = ""; }; + 2389732B0E115A999A069083 /* NotificationSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenCoordinator.swift; sourceTree = ""; }; + 23AA3F4B285570805CB0CCDD /* MapTiler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTiler.swift; sourceTree = ""; }; + 23E6EB7960BC9D0F7396B3BD /* RoomChangeRolesScreenRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenRow.swift; sourceTree = ""; }; + 23EE69982BBA18C6D51AD08E /* UserProfileScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileScreen.swift; sourceTree = ""; }; + 240610DF32F3213BEC5611D7 /* BlockedUsersScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreenViewModelTests.swift; sourceTree = ""; }; + 2429224EB0EEA34D35CE9249 /* UserIndicatorControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorControllerTests.swift; sourceTree = ""; }; + 2441E2424E78A40FC95DBA76 /* AudioRecorderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecorderTests.swift; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + 2525D78FEA7E7B132ED85C58 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = ""; }; + 25586C0ADB814FEE9897DCAA /* BugReportHook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportHook.swift; sourceTree = ""; }; + 259E5B05BDE6E20C26CF11B4 /* PollInteractionHandlerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollInteractionHandlerProtocol.swift; sourceTree = ""; }; + 25E7E9B7FEAB6169D960C206 /* QRCodeLoginScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeLoginScreenViewModelTests.swift; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + 2757B1BE23DF8AA239937243 /* AudioConverterProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioConverterProtocol.swift; sourceTree = ""; }; + 277C20CDD5B64510401B6D0D /* ServerConfigurationScreenViewStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfigurationScreenViewStateTests.swift; sourceTree = ""; }; + 27A1AD6389A4659AF0CEAE62 /* NotificationServiceExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationServiceExtension.swift; sourceTree = ""; }; + 27A9E3FBE8A66B5A17AD7F74 /* AppRoutes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRoutes.swift; sourceTree = ""; }; + 27D0EA07BD545CC9F234DB8D /* UserDetailsEditScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDetailsEditScreenModels.swift; sourceTree = ""; }; + 28146817C61423CACCF942F5 /* CallScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenModels.swift; sourceTree = ""; }; + 283974987DA7EC61D2AB57D9 /* VoiceMessageCacheTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageCacheTests.swift; sourceTree = ""; }; + 284FEEB0789B8894E52A7F34 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; + 287FC98AF2664EAD79C0D902 /* UIDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIDevice.swift; sourceTree = ""; }; + 28C19F54A0C4FC9AB7ABD583 /* TextRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineItemContent.swift; sourceTree = ""; }; + 28C202C1C7E330F124981A31 /* GenericCallLinkWidgetDriver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenericCallLinkWidgetDriver.swift; sourceTree = ""; }; + 28EA8BE9EEDBD17555141C7E /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = el; path = el.lproj/Localizable.stringsdict; sourceTree = ""; }; + 2910422CB628D3B2BBE47449 /* SeparatorRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineView.swift; sourceTree = ""; }; + 295E28C3B9EAADF519BF2F44 /* AuthenticationFlowCoordinatorUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationFlowCoordinatorUITests.swift; sourceTree = ""; }; + 29A953B6C0C431DBF4DD00B4 /* RoomSummary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummary.swift; sourceTree = ""; }; + 2A5C6FBF97B6EED3D4FA5EFF /* AttributedStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringBuilder.swift; sourceTree = ""; }; + 2AB2C848BB9A7A9B618B7B89 /* TextBasedRoomTimelineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextBasedRoomTimelineTests.swift; sourceTree = ""; }; + 2AC3FDB58F57386741A4FC7F /* DeactivateAccountScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeactivateAccountScreenViewModel.swift; sourceTree = ""; }; + 2AE807361805463F5AEDD1CA /* VoiceMessagePreviewComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessagePreviewComposer.swift; sourceTree = ""; }; + 2AE83A3DD63BCFBB956FE5CB /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = nl; path = nl.lproj/Localizable.stringsdict; sourceTree = ""; }; + 2AF715D4FD4710EBB637D661 /* SettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenViewModelProtocol.swift; sourceTree = ""; }; + 2BA894BC09972DC45E497D37 /* TimelineInteractionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineInteractionHandler.swift; sourceTree = ""; }; + 2BB385E148DE55C85C0A02D6 /* SoftLogoutScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutScreenModels.swift; sourceTree = ""; }; + 2BDB3E65A79779EDA5D33D8A /* AudioPlayerState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayerState.swift; sourceTree = ""; }; + 2BFDCA5A09EE70BC17F2EFA7 /* URLComponents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLComponents.swift; sourceTree = ""; }; + 2C0197EAE9D45A662B8847B6 /* RoomTimelineControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerProtocol.swift; sourceTree = ""; }; + 2C39D91A31409775B0F4268F /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/InfoPlist.strings; sourceTree = ""; }; + 2CEBCB9676FCD1D0F13188DD /* StringTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringTests.swift; sourceTree = ""; }; + 2CF9FE7E0CF9F40D1509E63A /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = bg; path = bg.lproj/Localizable.stringsdict; sourceTree = ""; }; + 2D0946F77B696176E062D037 /* RoomMembersListScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenModels.swift; sourceTree = ""; }; + 2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemProxy.swift; sourceTree = ""; }; + 2D7A2C4A3A74F0D2FFE9356A /* MediaPlayerProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPlayerProviderTests.swift; sourceTree = ""; }; + 2DA3DBE1A42EAFF93889FA04 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/SAS.strings; sourceTree = ""; }; + 2DA4F09CB613C54FDC73AE6A /* ThreadDecorator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadDecorator.swift; sourceTree = ""; }; + 2DB0E533508094156D8024C3 /* TimelineStyler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStyler.swift; sourceTree = ""; }; + 2E11E7C396ED06A154CF6DF3 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/SAS.strings; sourceTree = ""; }; + 2E88534A39781D76487D59DF /* SecureBackupKeyBackupScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupKeyBackupScreenViewModelTests.swift; sourceTree = ""; }; + 2EFE1922F39398ABFB36DF3F /* RoomDetailsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsViewModelTests.swift; sourceTree = ""; }; + 2F06F70B9C433BAD4BC6B9F5 /* EncryptedRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptedRoomTimelineView.swift; sourceTree = ""; }; + 2F36C5D9B37E50915ECBD3EE /* RoomMemberProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxy.swift; sourceTree = ""; }; + 303D9438EFB481F57A366E82 /* EncryptionResetPasswordScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreenViewModel.swift; sourceTree = ""; }; + 303FCADE77DF1F3670C086ED /* BugReportScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenViewModel.swift; sourceTree = ""; }; + 306AB507E1027D6C5C147EB6 /* EncryptionResetScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetScreenModels.swift; sourceTree = ""; }; + 307702DD66E7DDCDD9214784 /* IdentityConfirmedScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmedScreen.swift; sourceTree = ""; }; + 309AD8BAE6437C31BA7157BF /* ElementCallWidgetDriver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallWidgetDriver.swift; sourceTree = ""; }; + 30ED584467DB380E3CEFB1DB /* NotificationManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManagerTests.swift; sourceTree = ""; }; + 314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadReceipt.swift; sourceTree = ""; }; + 31A6314FDC51DA25712D9A81 /* PillContextTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillContextTests.swift; sourceTree = ""; }; + 31D6764D6976D235926FE5FC /* HomeScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModel.swift; sourceTree = ""; }; + 3203C6566DC17B7AECC1B7FD /* RoomNotificationSettingsUserDefinedScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsUserDefinedScreen.swift; sourceTree = ""; }; + 32B5E17028C02DFA7DDA3931 /* RoomMemberProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxyProtocol.swift; sourceTree = ""; }; + 32C5DAA1773F57653BF1C4F9 /* SoftLogoutViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutViewModelTests.swift; sourceTree = ""; }; + 33035418BB35754232985871 /* TimelineReadReceiptsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReadReceiptsView.swift; sourceTree = ""; }; + 330AF4D121C3396F7A14B21D /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = id.lproj/SAS.strings; sourceTree = ""; }; + 3339B1DDB1341E833D2555BC /* AVMetadataMachineReadableCodeObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AVMetadataMachineReadableCodeObject.swift; sourceTree = ""; }; + 3368395F06AA180138E185B6 /* PollFormScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenUITests.swift; sourceTree = ""; }; + 33AE897D86784CCA5E4E9227 /* ElementCallService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallService.swift; sourceTree = ""; }; + 33E49C5C6F802B4D94CA78D1 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/Localizable.strings; sourceTree = ""; }; + 340179A0FC1AD4AEDA7FC134 /* CreateRoomViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomViewModelProtocol.swift; sourceTree = ""; }; + 342BEBC3C5FC3F9943C41C4C /* TemplateScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreenViewModelProtocol.swift; sourceTree = ""; }; + 345172AD4377E83A44BD864F /* MessageComposerTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageComposerTextField.swift; sourceTree = ""; }; + 347D708104CCEF771428C9A3 /* PollFormScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenViewModelTests.swift; sourceTree = ""; }; + 34E0FA38BD473FFA6F1AB7A5 /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = be; path = be.lproj/Localizable.stringsdict; sourceTree = ""; }; + 34ED3AB7E0287552A5648AB3 /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = be.lproj/InfoPlist.strings; sourceTree = ""; }; + 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 = ""; }; + 36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxyMock.swift; sourceTree = ""; }; + 376D941BF8BB294389C0DE24 /* MapTilerURLBuildersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerURLBuildersTests.swift; sourceTree = ""; }; + 37A243E04B58DC6E41FDCD82 /* EmojiItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiItem.swift; sourceTree = ""; }; + 37A63A59BFDDC494B1C20119 /* CallScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenViewModel.swift; sourceTree = ""; }; + 37CA26F55123E36B50DB0B3A /* AttributedStringTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringTests.swift; sourceTree = ""; }; + 37FEE10AB666891E6A675E5E /* SecureBackupLogoutConfirmationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreen.swift; sourceTree = ""; }; + 382B50F7E379B3DBBD174364 /* NotificationSettingsProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsProxyMock.swift; sourceTree = ""; }; + 38345442415E07A931197C55 /* AppLockScreenPINKeypad.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockScreenPINKeypad.swift; sourceTree = ""; }; + 38354164AF59C5006CD05878 /* GlobalSearchScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchScreenViewModel.swift; sourceTree = ""; }; + 3865AD7B7249C939D7C69C33 /* CertificateValidatorHook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CertificateValidatorHook.swift; sourceTree = ""; }; + 38E521D6C2BF8DF0DFB35146 /* DeveloperOptionsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreen.swift; sourceTree = ""; }; + 3984C93B8E9B10C92DADF9EE /* RoomDirectorySearchScreenScreenModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreenScreenModelProtocol.swift; sourceTree = ""; }; + 398817652FA8ABAE0A31AC6D /* ReadableFrameModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadableFrameModifier.swift; sourceTree = ""; }; + 39C0D861FC397AC34BCF089E /* KeychainControllerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainControllerMock.swift; sourceTree = ""; }; + 3A12D3D8138F1B71AFA7C858 /* CompletionSuggestionService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletionSuggestionService.swift; sourceTree = ""; }; + 3AD253E7EFF88F308D644272 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/SAS.strings"; sourceTree = ""; }; + 3B5E97E9615A158C76B2AB77 /* DateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTests.swift; sourceTree = ""; }; + 3BAC027034248429A438886B /* AppMediatorMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppMediatorMock.swift; sourceTree = ""; }; + 3BC1B7CB061C9865B2B91B56 /* QRCodeLoginScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeLoginScreenViewModel.swift; sourceTree = ""; }; + 3BDCCD2F6B405C14B9BCE94E /* JoinRoomScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinRoomScreenCoordinator.swift; sourceTree = ""; }; + 3C1A3D524D63815B28FA4D62 /* EmojiCategory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiCategory.swift; sourceTree = ""; }; + 3C368CAB3063EF275357ECD4 /* LoginScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreenViewModel.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 = ""; }; + 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 = ""; }; + 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 = ""; }; + 3DC1943ADE6A62ED5129D7C8 /* LoggingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggingTests.swift; sourceTree = ""; }; + 3DFE4453AB0B34C203447162 /* ImageRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineItem.swift; sourceTree = ""; }; + 3E93A1BE7D8A2EBCAD51EEB4 /* Array.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Array.swift; sourceTree = ""; }; + 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 = ""; }; + 40B21E611DADDEF00307E7AC /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; }; + 4100DDE6BF3C566AB66B80CC /* MentionSuggestionItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MentionSuggestionItemView.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 = ""; }; + 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 = ""; }; + 421FA93BCC2840E66E4F306F /* NotificationSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenViewModelProtocol.swift; sourceTree = ""; }; + 42236480CF0431535EBE8387 /* CustomLayoutLabelStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomLayoutLabelStyle.swift; sourceTree = ""; }; + 422724361B6555364C43281E /* RoomHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomHeaderView.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 = ""; }; + 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 = ""; }; + 4481799F455B3DA243BDA2AC /* ShareToMapsAppActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareToMapsAppActivity.swift; sourceTree = ""; }; + 44ABA63DBE7F76C58260B43B /* EmoteRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineView.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 = ""; }; + 4525E8C0FBDD27D1ACE90952 /* SecureBackupKeyBackupScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupKeyBackupScreenViewModelProtocol.swift; sourceTree = ""; }; + 4549FCB53F43DB0B278374BC /* TemplateScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreen.swift; sourceTree = ""; }; + 4552D3466B1453F287223ADA /* SwipeRightAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeRightAction.swift; sourceTree = ""; }; + 45571C2EBD98ED7E0CEA7AF7 /* RoomRolesAndPermissionsUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomRolesAndPermissionsUITests.swift; sourceTree = ""; }; + 45CDF9A107BFE6C79B58D6B5 /* RoomMembersListScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenViewModelProtocol.swift; sourceTree = ""; }; + 45D8149FDDA0315CDC553B4B /* UserNotificationCenterProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationCenterProtocol.swift; sourceTree = ""; }; + 4629710C0337ADD9C8909542 /* ka */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ka; path = ka.lproj/Localizable.strings; sourceTree = ""; }; + 466C71A0FED9BFF287613C82 /* RoomDetailsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenModels.swift; sourceTree = ""; }; + 4691B8DE1D51DE152680098A /* HomeScreenSlidingSyncMigrationBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenSlidingSyncMigrationBanner.swift; sourceTree = ""; }; + 46A2AD86F7E618F468F6FAF5 /* VoiceMessageRecordingButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecordingButton.swift; sourceTree = ""; }; + 46C208DA43CE25D13E670F40 /* UITestsAppCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsAppCoordinator.swift; sourceTree = ""; }; + 46D0BA44B1838E65B507B277 /* NotificationPermissionsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPermissionsScreen.swift; sourceTree = ""; }; + 46D560DDA3B20C82766ACFAD /* NotificationSettingsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenViewModel.swift; sourceTree = ""; }; + 47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomProxyProtocol.swift; sourceTree = ""; }; + 471BB7276C97AF60B3A5463B /* RoomDirectorySearchProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchProxy.swift; sourceTree = ""; }; + 475D47D0BFE961B02BAC5D49 /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = id; path = id.lproj/Localizable.stringsdict; sourceTree = ""; }; + 475EB595D7527E9A8A14043E /* uz */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uz; path = uz.lproj/Localizable.strings; sourceTree = ""; }; + 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 = ""; }; + 4853C923A1AF43711D025EAF /* TextRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineView.swift; sourceTree = ""; }; + 48A5C34C4E4268EF65D171EF /* RoomChangeRolesScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenModels.swift; 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 = ""; }; + 4959CECEC984B3995616F427 /* DataProtectionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataProtectionManager.swift; sourceTree = ""; }; + 4999B5FD50AED7CB0F590FF8 /* AdvancedSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenModels.swift; sourceTree = ""; }; + 49ABAB186CF00B15C5521D04 /* MenuSheetLabelStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuSheetLabelStyle.swift; sourceTree = ""; }; + 49D2C8E66E83EA578A7F318A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 49E6066092ED45E36BB306F7 /* zh-Hant-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "zh-Hant-TW"; path = "zh-Hant-TW.lproj/Localizable.stringsdict"; sourceTree = ""; }; + 49E751D7EDB6043238111D90 /* UNNotificationRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UNNotificationRequest.swift; sourceTree = ""; }; + 4A2B5274C1D3D2999D643786 /* EncryptionResetPasswordScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreenViewModelProtocol.swift; sourceTree = ""; }; + 4A5B4CD611DE7E94F5BA87B2 /* AppLockTimerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockTimerTests.swift; sourceTree = ""; }; + 4B2D4EEBE8C098BBADD10939 /* SecureBackupKeyBackupScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupKeyBackupScreenCoordinator.swift; sourceTree = ""; }; + 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; }; + 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 = ""; }; + 4E600B315B920B9687F8EE1B /* ComposerDraftServiceMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerDraftServiceMock.swift; sourceTree = ""; }; + 4E625B0EB2F86B37C14EF7E6 /* SettingsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenViewModel.swift; sourceTree = ""; }; + 4E7F7A975514E850A834B29F /* PaginationIndicatorRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationIndicatorRoomTimelineView.swift; sourceTree = ""; }; + 4F5F0662483ED69791D63B16 /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = et; path = et.lproj/Localizable.stringsdict; sourceTree = ""; }; + 4F75EF13F49DD2204E760910 /* FileRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileRoomTimelineView.swift; sourceTree = ""; }; + 4FA29BAE9B0F2D90E57B261C /* UserSessionFlowCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionFlowCoordinatorTests.swift; sourceTree = ""; }; + 4FCB2126C091EEF2454B4D56 /* RoomFlowCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomFlowCoordinatorTests.swift; sourceTree = ""; }; + 4FD6E621CC5E6D4830D96D2D /* MockMediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockMediaProvider.swift; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + 510E89B989477E5EE8E503C0 /* PinnedEventsTimelineScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedEventsTimelineScreenViewModelProtocol.swift; sourceTree = ""; }; + 514363244AE7D68080D44C6F /* NotificationSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenViewModelTests.swift; sourceTree = ""; }; + 51C2BCE0BC1FC69C1B36E688 /* BugReportScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenModels.swift; sourceTree = ""; }; + 51C454AE59914B551A6D02C0 /* UserProfileProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileProxy.swift; sourceTree = ""; }; + 52135BD9E0E7A091688F627A /* MessageForwardingScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageForwardingScreenModels.swift; sourceTree = ""; }; + 5221DFDF809142A2D6AC82B9 /* RoomScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreen.swift; sourceTree = ""; }; + 5281C5CDC4A712265A0B5FBF /* PollRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollRoomTimelineItem.swift; sourceTree = ""; }; + 52BD6ED18E2EB61E28C340AD /* AttributedString.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedString.swift; sourceTree = ""; }; + 52D7074991B3267B26D89B22 /* MockRoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineController.swift; sourceTree = ""; }; + 52F5EE5DE3B55D59299DB5BC /* AppLockSetupBiometricsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreenViewModelTests.swift; sourceTree = ""; }; + 53482ECA4B6633961EC224F5 /* ScrollViewAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollViewAdapter.swift; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + 54A5E6F398C269AD52C9AE21 /* EncryptionResetPasswordScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreenModels.swift; sourceTree = ""; }; + 54AD70D6E03D2031AE1B5A52 /* TimelineReactionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReactionsView.swift; sourceTree = ""; }; + 54C4E7B46099462F12000C91 /* DeveloperOptionsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenViewModelProtocol.swift; sourceTree = ""; }; + 55AEEF8142DF1B59DB40FB93 /* TimelineItemSender.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemSender.swift; sourceTree = ""; }; + 5644919DB2022397D9D5825A /* MockSoftLogoutScreenState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSoftLogoutScreenState.swift; sourceTree = ""; }; + 565F1B2B300597C616B37888 /* FullscreenDialog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FullscreenDialog.swift; sourceTree = ""; }; + 56852036214ABA9D7D305768 /* ResolveVerifiedUserSendFailureScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResolveVerifiedUserSendFailureScreenViewModelProtocol.swift; sourceTree = ""; }; + 56D6F88FE35A0979D2821E06 /* AppLockScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockScreen.swift; sourceTree = ""; }; + 57084488B03BDB33C7B7CA0E /* ResolveVerifiedUserSendFailureScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResolveVerifiedUserSendFailureScreenViewModelTests.swift; sourceTree = ""; }; + 574CB70E82D7EAEA538E4135 /* ResolveVerifiedUserSendFailureScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResolveVerifiedUserSendFailureScreenViewModel.swift; sourceTree = ""; }; + 57916A1578D8043BB0795441 /* GeneratedMocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneratedMocks.swift; sourceTree = ""; }; + 57B6B383F1FD04CC0E7B60C6 /* AnalyticsConsentState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsConsentState.swift; sourceTree = ""; }; + 57EAAF82432B0B53881CF826 /* AudioRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRoomTimelineItem.swift; sourceTree = ""; }; + 57F95CADD0A5DBD76B990FCB /* ServiceLocator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceLocator.swift; sourceTree = ""; }; + 584A61D9C459FAFEF038A7C0 /* Section.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Section.swift; sourceTree = ""; }; + 5875F7C0A2398E9F134B1284 /* EncryptionResetScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetScreenViewModel.swift; sourceTree = ""; }; + 58C2527813FDAE23E72A9063 /* AnalyticsSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenViewModelTests.swift; sourceTree = ""; }; + 58D295F0081084F38DB20893 /* RoomNotificationSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModelTests.swift; sourceTree = ""; }; + 592A35163B0749C66BFD6186 /* MapLibreStaticMapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapLibreStaticMapView.swift; sourceTree = ""; }; + 595EC503DA5517BBE6D39406 /* IdentityConfirmedScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmedScreenCoordinator.swift; sourceTree = ""; }; + 596AA8843AC1A234F3387767 /* SecureBackupRecoveryKeyScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupRecoveryKeyScreenCoordinator.swift; sourceTree = ""; }; + 598F01EBD0C4CC550C644418 /* AuthenticationStartLogo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartLogo.swift; sourceTree = ""; }; + 59B7CC77B82C6C67DE3AD869 /* HighlightedTimelineItemModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HighlightedTimelineItemModifier.swift; sourceTree = ""; }; + 5A07692536D66E3DA32C4964 /* LogViewerScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewerScreen.swift; sourceTree = ""; }; + 5A1119E9C63AE530252640D2 /* SecureBackupController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupController.swift; sourceTree = ""; }; + 5A2FCA3D0F239B9E911B966B /* SecureBackupRecoveryKeyScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupRecoveryKeyScreen.swift; sourceTree = ""; }; + 5A37E2FACFD041CE466223CD /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 5AEA0B743847CFA5B3C38EE4 /* RoomMembersListScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenCoordinator.swift; sourceTree = ""; }; + 5B8F0ED874DF8C9A51B0AB6F /* SettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenCoordinator.swift; sourceTree = ""; }; + 5C7C7CFA6B2A62A685FF6CE3 /* DeveloperOptionsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenCoordinator.swift; sourceTree = ""; }; + 5CEEAE1BFAACD6C96B6DB731 /* PHGPostHogProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHGPostHogProtocol.swift; sourceTree = ""; }; + 5D26A086A8278D39B5756D6F /* project.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = project.yml; sourceTree = ""; }; + 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 = ""; }; + 5E75948AA1FE1D1A7809931F /* AuthenticationServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationServiceProtocol.swift; sourceTree = ""; }; + 5E9CBF577B9711CFBB4FA40D /* VoiceMessageRecordingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecordingView.swift; sourceTree = ""; }; + 5EB2CAA266B921D128C35710 /* LegalInformationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreenCoordinator.swift; sourceTree = ""; }; + 5F12E996BFBEB43815189ABF /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = uk; path = uk.lproj/Localizable.stringsdict; sourceTree = ""; }; + 5F4134FEFE4EB55759017408 /* UserSessionProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionProtocol.swift; sourceTree = ""; }; + 5FACD034DB52525A3CEF2BDF /* SessionVerificationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreen.swift; sourceTree = ""; }; + 60011EF0086E49DBD78E16E5 /* ResolveVerifiedUserSendFailureScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResolveVerifiedUserSendFailureScreenModels.swift; sourceTree = ""; }; + 6033779EB37259F27F938937 /* ClientProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientProxyProtocol.swift; sourceTree = ""; }; + 604A69C081B935D6A38DE6D8 /* UserProfileScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileScreenModels.swift; sourceTree = ""; }; + 60C9BAE9F9436B14E4E22E8F /* PinnedItemsBannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedItemsBannerView.swift; sourceTree = ""; }; + 60F18AECC9D38C2B6D85F99C /* Publisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Publisher.swift; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + 638A81B97D51591D0FCFA598 /* InteractiveQuickLook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractiveQuickLook.swift; sourceTree = ""; }; + 63E8A1E8EE094F570573B6E8 /* RoomDetailsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenViewModelProtocol.swift; sourceTree = ""; }; + 645E027C112740573D27765C /* SecureBackupRecoveryKeyScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupRecoveryKeyScreenModels.swift; sourceTree = ""; }; + 648DD1C10E4957CB791FE0B8 /* OverridableAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverridableAvatarImage.swift; sourceTree = ""; }; + 6493AC9979CEB1410302BFE3 /* RoomDetailsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenCoordinator.swift; sourceTree = ""; }; + 64F49FB9EE2913234F06CE68 /* MediaPickerScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPickerScreenCoordinator.swift; sourceTree = ""; }; + 6509708F54FC883604DFDC95 /* TimelineViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineViewModelTests.swift; sourceTree = ""; }; + 653610CB5F9776EAAAB98155 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = fr; path = fr.lproj/Localizable.stringsdict; sourceTree = ""; }; + 6569593FA36B22259E806A67 /* AudioRecorderState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecorderState.swift; sourceTree = ""; }; + 65AAD845E53B0C8B5E0812C2 /* UserDiscoveryService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDiscoveryService.swift; sourceTree = ""; }; + 664ABD745A746C45CB842158 /* CallInviteRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallInviteRoomTimelineView.swift; sourceTree = ""; }; + 6654859746B0BE9611459391 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = cs; path = cs.lproj/Localizable.stringsdict; sourceTree = ""; }; + 6663BFB9FDB8752562CD12CA /* AuthenticationStartScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenCoordinator.swift; sourceTree = ""; }; + 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 = ""; }; + 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProvider.swift; sourceTree = ""; }; + 66F91544AC136BF6477BDAB8 /* TimelineDeliveryStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineDeliveryStatusView.swift; sourceTree = ""; }; + 6722709BD6178E10B70C9641 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/SAS.strings; sourceTree = ""; }; + 68010886142843705E342645 /* ProgressMaskModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressMaskModifier.swift; sourceTree = ""; }; + 6861FE915C7B5466E6962BBA /* StartChatScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatScreen.swift; sourceTree = ""; }; + 693E16574C6F7F9FA1015A8C /* Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Search.swift; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + 6B2A421198FD20AAAED20004 /* RoomChangeRolesScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreen.swift; sourceTree = ""; }; + 6B5E29E9A22F45534FBD5B58 /* EmojiPickerScreenHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenHeaderView.swift; sourceTree = ""; }; + 6C113E0CB7E15E9765B1817A /* EmojiProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiProvider.swift; sourceTree = ""; }; + 6C8EC6EA7EDFCE46710DA306 /* AnalyticsPromptScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenViewModel.swift; sourceTree = ""; }; + 6CD4823EAB4B4E8BAB4F6B8C /* TimelineStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStyle.swift; sourceTree = ""; }; + 6CEBE5EA91E8691EDF364EC2 /* UITestsScreenIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsScreenIdentifier.swift; sourceTree = ""; }; + 6D0A27607AB09784C8501B5C /* DeveloperOptionsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenViewModelTests.swift; sourceTree = ""; }; + 6D4777F0142E330A75C46FE4 /* SessionVerificationUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationUITests.swift; sourceTree = ""; }; + 6DF438EAFC732D2D95D34BF6 /* StartChatViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatViewModelTests.swift; sourceTree = ""; }; + 6E5725BC6C63604CB769145B /* LegalInformationScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreenViewModelTests.swift; sourceTree = ""; }; + 6E5E9C044BEB7C70B1378E91 /* UserSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSession.swift; sourceTree = ""; }; + 6E964AF2DFEB31E2B799999F /* RoomPollsHistoryScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreenModels.swift; sourceTree = ""; }; + 6EA1D2CBAEA5D0BD00B90D1B /* BindableState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BindableState.swift; sourceTree = ""; }; + 6F1C3CBBC62C566DDF5E84C1 /* TimelineItemMenuAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemMenuAction.swift; sourceTree = ""; }; + 6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateStoreViewModel.swift; sourceTree = ""; }; + 6F418426410F3823F3EB0828 /* WebRegistrationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebRegistrationScreenViewModelProtocol.swift; sourceTree = ""; }; + 6F6E6EDC4BBF962B2ED595A4 /* MessageForwardingScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageForwardingScreenViewModelTests.swift; sourceTree = ""; }; + 6FA38E813BE14149F173F461 /* PinnedEventsBannerStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedEventsBannerStateTests.swift; sourceTree = ""; }; + 6FC5015B9634698BDB8701AF /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = it; path = it.lproj/Localizable.stringsdict; sourceTree = ""; }; + 6FC8B21E86B137BE4E91F82A /* ElementCallServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallServiceProtocol.swift; sourceTree = ""; }; + 7061BE2C0BF427C38AEDEF5E /* SecureBackupRecoveryKeyScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupRecoveryKeyScreenViewModel.swift; sourceTree = ""; }; + 70C86696AC9521F8ED88FBEB /* MediaUploadPreviewScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreen.swift; sourceTree = ""; }; + 713B48DBF65DE4B0DD445D66 /* ReportContentScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentScreenViewModelProtocol.swift; sourceTree = ""; }; + 718D8767035D37E2DB5CC550 /* QRCodeLoginScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeLoginScreenViewModelProtocol.swift; sourceTree = ""; }; + 7199693797B66245EF97BCF5 /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = id.lproj/InfoPlist.strings; sourceTree = ""; }; + 71A7D4DDEEE5D2CA0C8D63CD /* SoftLogoutScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutScreen.swift; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + 7367B3B9A8CAF902220F31D1 /* BugReportFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportFlowCoordinator.swift; sourceTree = ""; }; + 73A5C3F7C9C1DA10CAEC6A98 /* VoiceMessageRecordingComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecordingComposer.swift; sourceTree = ""; }; + 7447C0AD7EF302CD027D6230 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/SAS.strings; sourceTree = ""; }; + 74611A4182DCF5F4D42696EC /* XCTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCTestCase.swift; sourceTree = ""; }; + 7463464054DDF194C54F0B04 /* LogViewerScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewerScreenViewModelProtocol.swift; sourceTree = ""; }; + 74653BE903970C0E36867D46 /* GlobalSearchScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchScreenCoordinator.swift; sourceTree = ""; }; + 7475C5AE20BA896930907EA8 /* AudioRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRoomTimelineItemContent.swift; sourceTree = ""; }; + 748AE77AC3B0A01223033B87 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 74DD0855F2F76D47E5555082 /* MediaUploadPreviewScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenCoordinator.swift; sourceTree = ""; }; + 74E08B8A66948E9690F38B94 /* SecureBackupLogoutConfirmationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreenViewModelProtocol.swift; sourceTree = ""; }; + 7509AB72755DCC4B4E721B36 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/SAS.strings; sourceTree = ""; }; + 752A0EB49BF5BCEA37EDF7A3 /* Signposter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Signposter.swift; sourceTree = ""; }; + 753B4C6C0EDDCBF0708DC384 /* TimelineItemSendInfoLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemSendInfoLabel.swift; sourceTree = ""; }; + 76310030C831D4610A705603 /* URLComponentsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLComponentsTests.swift; sourceTree = ""; }; + 7773CBFDBD458E0B7E270507 /* PillView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillView.swift; sourceTree = ""; }; + 780258F1B9D15E30549FF4BE /* NotificationSettingsEditScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsEditScreenViewModel.swift; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + 7AE75941583A033A9EDC9FE0 /* RoomChangePermissionsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangePermissionsScreenViewModel.swift; sourceTree = ""; }; + 7AFD012C3A9F5EF276DDD4AA /* AnalyticsPromptScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenViewModelProtocol.swift; sourceTree = ""; }; + 7B04BD3874D736127A8156B8 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = ""; }; + 7B19B2BCC779ED934E0BBC2A /* AudioPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayer.swift; sourceTree = ""; }; + 7B25F959A434BB9923A3223F /* ExpiringTaskRunner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpiringTaskRunner.swift; sourceTree = ""; }; + 7B3D16709ADD4F4BCC710B1E /* SecureBackupScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupScreenModels.swift; sourceTree = ""; }; + 7B849D2FF2CC12BA411A1651 /* CreateRoomModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomModels.swift; sourceTree = ""; }; + 7B9FCA1CFD07B8CF9BD21266 /* FlowCoordinatorProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlowCoordinatorProtocol.swift; sourceTree = ""; }; + 7C1AF829F12FDC99717082D9 /* RoomRolesAndPermissionsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomRolesAndPermissionsScreenViewModel.swift; sourceTree = ""; }; + 7C28B70BEFD3676F11D5D51F /* RoomRolesAndPermissionsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomRolesAndPermissionsScreenCoordinator.swift; sourceTree = ""; }; + 7C71B9802433F1B4252291BB /* IdentityConfirmationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreenViewModelProtocol.swift; sourceTree = ""; }; + 7D0CBC76C80E04345E11F2DB /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = ""; }; + 7D25A35764C7B3DB78954AB5 /* RoomTimelineItemFactoryProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFactoryProtocol.swift; sourceTree = ""; }; + 7D39AF1F659923D77778511E /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/InfoPlist.strings; sourceTree = ""; }; + 7DC017C3CB6B0F7C63F460F2 /* SecureBackupLogoutConfirmationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreenViewModel.swift; sourceTree = ""; }; + 7DDBF99755A9008CF8C8499E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 7DDF49CEBC0DFC59C308335F /* RoomMemberDetailsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsScreenViewModelProtocol.swift; sourceTree = ""; }; + 7E492690C8B27A892C194CC4 /* AdvancedSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenCoordinator.swift; sourceTree = ""; }; + 7E8562F4D7DE073BC32902AB /* EncryptionResetScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetScreenViewModelProtocol.swift; sourceTree = ""; }; + 7EB58E4E8D6D634C246AD5C2 /* RoomInviterLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomInviterLabel.swift; sourceTree = ""; }; + 7EC2F1622C5BBABED6012E12 /* HeroImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeroImage.swift; sourceTree = ""; }; + 7EECE8B331CD169790EF284F /* BugReportScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenViewModelTests.swift; sourceTree = ""; }; + 7F615A00DB223FF3280204D2 /* UserDiscoveryServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDiscoveryServiceProtocol.swift; sourceTree = ""; }; + 7FB2253D36E81E045E1CB432 /* Duration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Duration.swift; sourceTree = ""; }; + 7FDF541AE914059942B575B4 /* IdentityConfirmationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreenModels.swift; sourceTree = ""; }; + 8063E65441E771200108C558 /* ReadReceiptsSummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadReceiptsSummaryView.swift; sourceTree = ""; }; + 80E815FF3CC5E5A355E3A25E /* RoomMessageEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMessageEventStringBuilder.swift; 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 = ""; }; + 8166F121C79C7B62BF01D508 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = pt; path = pt.lproj/Localizable.stringsdict; sourceTree = ""; }; + 818695BED971753243FEF897 /* StickerRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StickerRoomTimelineItem.swift; sourceTree = ""; }; + 81A9B5225D0881CEFA2CF7C9 /* RoomNotificationSettingsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModel.swift; sourceTree = ""; }; + 81B17B1F29448D1B9049B11C /* ReportContentScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentScreenViewModel.swift; sourceTree = ""; }; + 81B17DB1BC3B0C62AF84D230 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 81F0325E252B057FAEEE1B2D /* TypingIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TypingIndicatorView.swift; sourceTree = ""; }; + 8296D6FB451E25CEC0767BBA /* RoomNotificationSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenCoordinator.swift; sourceTree = ""; }; + 82B612853BFB68373249777B /* SecureBackupKeyBackupScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupKeyBackupScreenViewModel.swift; sourceTree = ""; }; + 82DFA1B7B088D033E0794B82 /* RoomChangeRolesScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenCoordinator.swift; sourceTree = ""; }; + 82EE3B877D91030248B1242D /* DeactivateAccountScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeactivateAccountScreenViewModelProtocol.swift; sourceTree = ""; }; + 8319173DD66C07F45DC48848 /* IdentityConfirmedScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmedScreenViewModelProtocol.swift; sourceTree = ""; }; + 837B440C4705E4B899BCB899 /* RoomDetailsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenViewModel.swift; sourceTree = ""; }; + 839E2C35DF3F9C7B54C3CE49 /* RoundedCornerShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedCornerShape.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 = ""; }; + 84A00BB9CD12CF6AC98D5485 /* SecureBackupScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupScreen.swift; sourceTree = ""; }; + 84A87D0471D438A233C2CF4A /* RoomMemberDetailsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsScreenViewModel.swift; sourceTree = ""; }; + 84AF32E4136FD6F159D86C2C /* RoomDirectorySearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchView.swift; sourceTree = ""; }; + 84B7A28A6606D58D1E38C55A /* ExpiringTaskRunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpiringTaskRunnerTests.swift; sourceTree = ""; }; + 85149F56BA333619900E2410 /* UserDetailsEditScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDetailsEditScreenViewModelProtocol.swift; sourceTree = ""; }; + 851B95BB98649B8E773D6790 /* AppLockService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockService.swift; sourceTree = ""; }; + 8544F7058D31DBEB8DBFF0F5 /* NotificationSettingsEditScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsEditScreenViewModelTests.swift; sourceTree = ""; }; + 854BCEAF2A832176FAACD2CB /* SplashScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashScreenCoordinator.swift; sourceTree = ""; }; + 85666E40F7E817809B4FD787 /* ComposerToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerToolbar.swift; sourceTree = ""; }; + 8585C636A10B8141A7AE909F /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/InfoPlist.strings; sourceTree = ""; }; + 85EB16E7FE59A947CA441531 /* MediaProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProviderProtocol.swift; sourceTree = ""; }; + 8609BE4CA71C30D1FCE3AF9B /* AuthenticationStartScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenModels.swift; sourceTree = ""; }; + 8610C1D21565C950BCA6A454 /* AppLockSetupSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupSettingsScreenViewModelProtocol.swift; sourceTree = ""; }; + 86376BEE425704AEE197CA54 /* PillContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillContext.swift; sourceTree = ""; }; + 8642512079EEFD622E3AA66B /* BlockedUsersScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreenModels.swift; sourceTree = ""; }; + 867DC9530C42F7B5176BE465 /* JoinedRoomProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinedRoomProxyMock.swift; sourceTree = ""; }; + 869A8A4632E511351BFE2EC4 /* JoinRoomScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinRoomScreen.swift; sourceTree = ""; }; + 86A6F283BC574FDB96ABBB07 /* DeveloperOptionsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenViewModel.swift; sourceTree = ""; }; + 86C8CE2630F54D5FE1591786 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/InfoPlist.strings; sourceTree = ""; }; + 86D7CD5CA270BFC3EBB450CA /* PinnedEventsTimelineScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedEventsTimelineScreenViewModel.swift; sourceTree = ""; }; + 88410BD213FDF9B28E8B671F /* UserDetailsEditScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDetailsEditScreen.swift; sourceTree = ""; }; + 8896CDD20CA2D87EA3B848A1 /* RoomNotificationSettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreen.swift; sourceTree = ""; }; + 889DEDD63C68ABDA8AD29812 /* VoiceMessageMediaManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageMediaManagerProtocol.swift; sourceTree = ""; }; + 89233612A8632AD7E2803620 /* AudioPlayerStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayerStateTests.swift; sourceTree = ""; }; + 893777A4997BBDB68079D4F5 /* ArrayTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrayTests.swift; sourceTree = ""; }; + 894EE8F5B399A165BA2A6634 /* RoomDirectorySearchMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchMock.swift; sourceTree = ""; }; + 8977176AB534AA41630395BC /* LegalInformationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreenViewModelProtocol.swift; sourceTree = ""; }; + 897DF5E9A70CE05A632FC8AF /* UTType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UTType.swift; sourceTree = ""; }; + 89AAEA70CFF3284920811941 /* RoomChangePermissionsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangePermissionsScreen.swift; sourceTree = ""; }; + 89FBFC09F9DAFF1E4BA97849 /* FormButtonStyles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormButtonStyles.swift; sourceTree = ""; }; + 8A1009E4A78F86DA42E1EAF0 /* DeactivateAccountScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeactivateAccountScreenCoordinator.swift; sourceTree = ""; }; + 8A9AE4967817E9608E22EB44 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = ""; }; + 8AE0C9653870803E4F91F474 /* RoomListFiltersStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomListFiltersStateTests.swift; sourceTree = ""; }; + 8AE78FA0011E07920AE83135 /* PlainMentionBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlainMentionBuilder.swift; sourceTree = ""; }; + 8AFCE895ECFFA53FEE64D62B /* MediaLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaLoader.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 = ""; }; + 8CC23C63849452BC86EA2852 /* ButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonStyle.swift; sourceTree = ""; }; + 8D1FA20DAB853C1156054912 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/InfoPlist.strings; sourceTree = ""; }; + 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 = ""; }; + 8E1584F8BCF407BB94F48F04 /* EncryptionResetPasswordScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreen.swift; sourceTree = ""; }; + 8F21ED7205048668BEB44A38 /* AppActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppActivityView.swift; sourceTree = ""; }; + 8F6210134203BE1F2DD5C679 /* RoomDirectoryCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectoryCell.swift; sourceTree = ""; }; + 8F841F219ACDFC1D3F42FEFB /* RoomChangeRolesScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenViewModelTests.swift; sourceTree = ""; }; + 8FB89DC7F9A4A91020037001 /* AuthenticationStartScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenViewModelTests.swift; sourceTree = ""; }; + 8FC803282F9268D49F4ABF14 /* AppCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCoordinator.swift; sourceTree = ""; }; + 90791B9C739C716A40E1B230 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; + 907FA4DE17DEA1A3738EFB83 /* AudioRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecorder.swift; sourceTree = ""; }; + 90A55430639712CFACA34F43 /* TextRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineItem.swift; sourceTree = ""; }; + 90DFF217B3D9D0941283278C /* RoomRolesAndPermissionsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomRolesAndPermissionsScreenViewModelProtocol.swift; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + 92390F9FA98255440A6BF5F8 /* OIDCAuthenticationPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OIDCAuthenticationPresenter.swift; sourceTree = ""; }; + 92DB574F954CC2B40F7BE892 /* QRCodeScannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeScannerView.swift; sourceTree = ""; }; + 9332DFE9642F0A46ECA0497B /* BlurHashEncode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlurHashEncode.swift; sourceTree = ""; }; + 933B074F006F8E930DB98B4E /* TimelineMediaFrame.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaFrame.swift; sourceTree = ""; }; + 9342F5D6729627B6393AF853 /* ServerConfirmationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenModels.swift; sourceTree = ""; }; + 9349F590E35CE514A71E6764 /* LoginHomeserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginHomeserver.swift; sourceTree = ""; }; + 935C2FB18EFB8EEE96B26330 /* CreateRoomFlowParameters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomFlowParameters.swift; sourceTree = ""; }; + 93C713D124FE915ABF47A6B7 /* TimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineView.swift; sourceTree = ""; }; + 93CF7B19FFCF8EFBE0A8696A /* RoomScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModelTests.swift; sourceTree = ""; }; + 93E1FF0DFBB3768F79FDBF6D /* AVMetadataMachineReadableCodeObjectExtensionsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AVMetadataMachineReadableCodeObjectExtensionsTest.swift; sourceTree = ""; }; + 93E7304F5ECB4CB11CB10E60 /* SecureBackupRecoveryKeyScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupRecoveryKeyScreenViewModelProtocol.swift; sourceTree = ""; }; + 94028A227645FA880B966211 /* WaveformSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaveformSource.swift; sourceTree = ""; }; + 94D670124FC3E84F23A62CCF /* APNSPayload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APNSPayload.swift; sourceTree = ""; }; + 9501D11B4258DFA33BA3B40F /* ServerSelectionScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionScreenModels.swift; sourceTree = ""; }; + 955336CBD5ED73C792D1F580 /* EncryptionAuthenticity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionAuthenticity.swift; sourceTree = ""; }; + 95A2E4BD7C0CAD25EF924A4C /* GeneratedPreviewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneratedPreviewTests.swift; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + 97B2ACA28A854E41AE3AC9AD /* TimelineViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineViewModel.swift; sourceTree = ""; }; + 97C8E13A1FBA717B0C277ECC /* ProgressCursorModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressCursorModifier.swift; sourceTree = ""; }; + 97CE98208321C4D66E363612 /* ShimmerModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShimmerModifier.swift; sourceTree = ""; }; + 981663D961C94270FA035FD0 /* Alert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Alert.swift; sourceTree = ""; }; + 9873076F224E4CE09D8BD47D /* TemplateScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreenUITests.swift; sourceTree = ""; }; + 989D7380D9C86B3A10D30B13 /* AppLockSetupPINScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreenViewModelTests.swift; sourceTree = ""; }; + 989FC684408B31A677F5538B /* CompletionSuggestionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletionSuggestionView.swift; sourceTree = ""; }; + 997BF045585AF6DB2EBC5755 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/InfoPlist.strings; sourceTree = ""; }; + 9A008E57D52B07B78DFAD1BB /* RoomFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomFlowCoordinator.swift; sourceTree = ""; }; + 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 = ""; }; + 9B6572E6EF5D5F4B0C338A40 /* PinnedEventsTimelineScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedEventsTimelineScreenModels.swift; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + 9C6624240FFD32B7F0834229 /* IdentityConfirmedScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmedScreenViewModel.swift; sourceTree = ""; }; + 9C698E30698EC59302A8EEBD /* NavigationStackCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationStackCoordinatorTests.swift; sourceTree = ""; }; + 9C7F7DE62D33C6A26CBFCD72 /* IntegrationTests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = IntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 9CE3C90E487B255B735D73C8 /* RoomScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModel.swift; sourceTree = ""; }; + 9CF1EE0AA78470C674554262 /* PillTextAttachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillTextAttachment.swift; sourceTree = ""; }; + 9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIConstants.swift; sourceTree = ""; }; + 9ECF11669EF253E98AA2977A /* CompletionSuggestionServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletionSuggestionServiceProtocol.swift; sourceTree = ""; }; + 9F1DF3FFFE5ED2B8133F43A7 /* MessageComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageComposer.swift; sourceTree = ""; }; + 9F40FB0A43DAECEC27C73722 /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg; path = bg.lproj/SAS.strings; sourceTree = ""; }; + 9F85164F9475FF2867F71AAA /* RoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineController.swift; sourceTree = ""; }; + A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModelProtocol.swift; sourceTree = ""; }; + A010B8EAD1A9F6B4686DF2F4 /* BlockedUsersScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreenViewModel.swift; sourceTree = ""; }; + A019A12C866D64CF072024B9 /* AppLockSetupPINScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreenViewModel.swift; sourceTree = ""; }; + A02D1A490944BF01A37586E1 /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/SAS.strings; sourceTree = ""; }; + A05707BF550D770168A406DB /* LoginViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewModelTests.swift; sourceTree = ""; }; + A057F2FDC14866C3026A89A4 /* NotificationManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManagerProtocol.swift; sourceTree = ""; }; + A12D3B1BCF920880CA8BBB6B /* UserIndicatorControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorControllerProtocol.swift; sourceTree = ""; }; + A130A2251A15A7AACC84FD37 /* RoomPollsHistoryScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreenViewModelProtocol.swift; sourceTree = ""; }; + A16CD2C62CB7DB78A4238485 /* ReportContentScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentScreenCoordinator.swift; sourceTree = ""; }; + A16D0F226B1819D017531647 /* BlockedUsersScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreenCoordinator.swift; sourceTree = ""; }; + A1C22B1B5FA3A765EADB2CC9 /* SessionVerificationStateMachineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationStateMachineTests.swift; sourceTree = ""; }; + A232D9156D225BD9FD1D0C43 /* PhotoLibraryPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoLibraryPicker.swift; sourceTree = ""; }; + A243A6E6207297123E60DE48 /* TimelineItemMacContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemMacContextMenu.swift; sourceTree = ""; }; + A3B4B58B79A6FA250B24A1EC /* HomeScreenContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenContent.swift; sourceTree = ""; }; + A3FBD9C2B9A5479526920399 /* BugReportScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenCoordinator.swift; sourceTree = ""; }; + A40C19719687984FD9478FBE /* Task.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Task.swift; sourceTree = ""; }; + A40F1985065500F0E7F61A27 /* PollFormScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenViewModelProtocol.swift; sourceTree = ""; }; + A433BE28B40D418237BE37B5 /* ReportContentScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentScreen.swift; sourceTree = ""; }; + A436057DBEA1A23CA8CB1FD7 /* UIFont+AttributedStringBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIFont+AttributedStringBuilder.h"; sourceTree = ""; }; + A443FAE2EE820A5790C35C8D /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/Localizable.strings; sourceTree = ""; }; + A4A1003A0F7A1DFB47F4E2D0 /* TimelineItemMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemMock.swift; sourceTree = ""; }; + A54AAF72E821B4084B7E4298 /* PinnedEventsTimelineFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedEventsTimelineFlowCoordinator.swift; sourceTree = ""; }; + A58E93D91DE3288010390DEE /* EmojiDetectionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiDetectionTests.swift; sourceTree = ""; }; + A6702BC84D3CC2421D78CD4E /* WebRegistrationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebRegistrationScreenViewModel.swift; sourceTree = ""; }; + A69869844D2B6F5BD9AABF85 /* OIDCConfigurationProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OIDCConfigurationProxy.swift; sourceTree = ""; }; + A6B19D10B102956066AF117B /* PollOptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollOptionView.swift; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + 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 = ""; }; + 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 = ""; }; + A9B069D7772DDF6513E0F1B8 /* AuthenticationFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationFlowCoordinator.swift; sourceTree = ""; }; + A9E6065FC6BC4A1B4C629E08 /* TimelineItemMenuActionProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemMenuActionProvider.swift; 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; }; + AACE9B8E1A4AE79A7E2914F6 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = es; path = es.lproj/Localizable.stringsdict; sourceTree = ""; }; + AAD01F7FC2BBAC7351948595 /* UserProfile+Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserProfile+Mock.swift"; sourceTree = ""; }; + AAD8234D0E9C9B12BF9F240B /* LocationAnnotation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationAnnotation.swift; sourceTree = ""; }; + AB26D5444A4A7E095222DE8B /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.stringsdict"; sourceTree = ""; }; + ABA4CF2F5B4F68D02E412004 /* ServerConfirmationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenViewModelProtocol.swift; sourceTree = ""; }; + AC0275CEE9CA078B34028BDF /* AppLockScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockScreenViewModelTests.swift; sourceTree = ""; }; + AC1DA29A5A041CC0BACA7CB0 /* MockImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockImageCache.swift; sourceTree = ""; }; + AC3F82523D6F48B926D6AF68 /* AppSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettings.swift; sourceTree = ""; }; + AC4F10BDD56FA77FEC742333 /* VoiceMessageMediaManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageMediaManagerTests.swift; sourceTree = ""; }; + AC5F5209279A752D98AAC4B2 /* CollapsibleFlowLayoutTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleFlowLayoutTests.swift; sourceTree = ""; }; + AC9104846487244648D32C6D /* AudioPlayerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayerProtocol.swift; sourceTree = ""; }; + ACA11F7F50A4A3887A18CA5A /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = ""; }; + ACD7BD6BEE21264F6677904A /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/InfoPlist.strings; sourceTree = ""; }; + AD0FF64B0E6470F66F42E182 /* EstimatedWaveformView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EstimatedWaveformView.swift; sourceTree = ""; }; + AD378D580A41E42560C60E9C /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/Localizable.strings; sourceTree = ""; }; + AD558A898847C179E4B7A237 /* SecureBackupKeyBackupScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupKeyBackupScreen.swift; sourceTree = ""; }; + AD6B522BD637845AB9570B10 /* RoomNotificationSettingsProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsProxy.swift; sourceTree = ""; }; + AD6E082B0507FB28F966516A /* CallNotificationRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallNotificationRoomTimelineView.swift; sourceTree = ""; }; + AD72A9B720D75DBE60AC299F /* SecureBackupKeyBackupScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupKeyBackupScreenModels.swift; sourceTree = ""; }; + AD9AD6AE5FC868962F090740 /* CallScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenViewModelProtocol.swift; sourceTree = ""; }; + AD9CB3B9DFA353AB2B7CD9F8 /* NotificationSettingsEditScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsEditScreenCoordinator.swift; sourceTree = ""; }; + ADCB8A232D3A8FB3E16A7303 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Localizable.strings; sourceTree = ""; }; + AE203026B9AD3DB412439866 /* MediaUploadingPreprocessorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadingPreprocessorTests.swift; sourceTree = ""; }; + AE40D4A5DD857AC16EED945A /* URLSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSession.swift; sourceTree = ""; }; + AE52983FAFB4E0998C00EE8A /* CancellableTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CancellableTask.swift; sourceTree = ""; }; + AE5DDBEBBA17973ED4638823 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = de; path = de.lproj/Localizable.stringsdict; sourceTree = ""; }; + 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 = ""; }; + AFEF489B8E2450E2BA1A314E /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/SAS.strings; sourceTree = ""; }; + B050A6B233D95807A09289E7 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = wrapper.cfbundle; path = Settings.bundle; sourceTree = ""; }; + B0618820D26F9871A4BBB40E /* ComposerToolbarViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerToolbarViewModelProtocol.swift; sourceTree = ""; }; + B0A307A44F952CD73E63AE31 /* RoomEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomEventStringBuilder.swift; sourceTree = ""; }; + B0BA67B3E4EF9D29D14A78CE /* AppLockSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSettingsScreenViewModelTests.swift; sourceTree = ""; }; + B14B1DE3E2D5D26732C49036 /* RoomChangeRolesScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenViewModel.swift; sourceTree = ""; }; + B16048D30F0438731C41F775 /* StateRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateRoomTimelineItem.swift; sourceTree = ""; }; + B172057567E049007A5C4D92 /* Strings+SAS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Strings+SAS.swift"; sourceTree = ""; }; + B1E227F34BE43B08E098796E /* TestablePreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestablePreview.swift; sourceTree = ""; }; + B251F5B4511D1CA0BA8361FE /* CoordinatorProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoordinatorProtocol.swift; sourceTree = ""; }; + B2AD8A56CD37E23071A2F4BF /* PHGPostHogMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHGPostHogMock.swift; sourceTree = ""; }; + B2AF1828A5B76B7C371240FE /* StateRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateRoomTimelineView.swift; sourceTree = ""; }; + B2B1DC3B3FB40A7F4AE9B7BF /* RoomRolesAndPermissionsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomRolesAndPermissionsScreen.swift; sourceTree = ""; }; + B2B5EDCD05D50BA9B815C66C /* ImageRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineItemContent.swift; sourceTree = ""; }; + B2E7C987AE5DC9087BB19F7D /* MediaUploadPreviewScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenModels.swift; sourceTree = ""; }; + B2EAFFD44F81F86012D6EC27 /* AudioRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRoomTimelineView.swift; sourceTree = ""; }; + B3005886F00029F058DB62BE /* StartChatScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatScreenCoordinator.swift; sourceTree = ""; }; + B383DCD3DCB19E00FD478A5F /* ConfirmationDialog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmationDialog.swift; sourceTree = ""; }; + B3A1398EFF65090FDA1CB639 /* ProcessInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProcessInfo.swift; sourceTree = ""; }; + B4005D82E9D27BAF006A8FE1 /* AppLockScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockScreenViewModel.swift; sourceTree = ""; }; + B40233F2989AD49906BB310D /* RoomPollsHistoryScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreenViewModelTests.swift; sourceTree = ""; }; + B410B32B72C90BF94E481F33 /* AppLockSetupPINScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreenModels.swift; sourceTree = ""; }; + B43456E73F8A2D52B69B9FB9 /* TemplateScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreenViewModel.swift; sourceTree = ""; }; + B4427AF4B7FB7EF3E3D424C7 /* QRCodeLoginService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeLoginService.swift; sourceTree = ""; }; + B48B7AD4908C5C374517B892 /* MapAssets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = MapAssets.xcassets; sourceTree = ""; }; + B4CFE236419E830E8946639C /* Analytics+SwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Analytics+SwiftUI.swift"; sourceTree = ""; }; + B50F03079F6B5EF9CA005F14 /* TimelineProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxyProtocol.swift; sourceTree = ""; }; + B53AC78E49A297AC1D72A7CF /* AppMediator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppMediator.swift; sourceTree = ""; }; + B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadableAvatarImage.swift; 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 = ""; }; + B6E4AB573FAEBB7B853DD04C /* AppHooks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppHooks.swift; sourceTree = ""; }; + B6E89E530A8E92EC44301CA1 /* Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bundle.swift; sourceTree = ""; }; + B70A50C41C5871B4DB905E7E /* VoiceMessageRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRoomTimelineView.swift; sourceTree = ""; }; + B73587C2E3CF5998361AE516 /* HomeScreenRoomTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenRoomTests.swift; sourceTree = ""; }; + B746EFA112532A7B701FB914 /* RoomNotificationSettingsCustomSectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsCustomSectionView.swift; sourceTree = ""; }; + B7884BD256C091EB511B2EDF /* AppLockSetupPINScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreenViewModelProtocol.swift; sourceTree = ""; }; + B788615712FED326F73D3F83 /* GlobalSearchScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchScreenViewModelProtocol.swift; sourceTree = ""; }; + B7AE92E7BFF71797BDE1D261 /* MapTilerStyleBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerStyleBuilder.swift; sourceTree = ""; }; + B7F0192CE2F891141A25B49F /* UITestsSignalling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsSignalling.swift; sourceTree = ""; }; + B8108C8F0ACF6A7EB72D0117 /* RoomScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenCoordinator.swift; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + B99E13633862847D8B7E2815 /* StartChatScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatScreenModels.swift; sourceTree = ""; }; + BA241DEEF7C8A7181C0AEDC9 /* UserPreferenceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPreferenceTests.swift; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + 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 = ""; }; + BE78CAD0B964C66FD06EF83E /* DeactivateAccountScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeactivateAccountScreenModels.swift; sourceTree = ""; }; + BE89A8BD65CCE3FCC925CA14 /* TimelineItemReplyDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemReplyDetails.swift; 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 = ""; }; + BEE365C5A4E90ACBE398EFFE /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/SAS.strings; sourceTree = ""; }; + BEF5FE93A06F563B477F024A /* RoomAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomAvatarImage.swift; sourceTree = ""; }; + BF34A2FD6797535C95AC918D /* PlaceholderScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderScreenCoordinator.swift; sourceTree = ""; }; + BFA9EA59D5C0DA1BFC7B3621 /* QRCodeLoginScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeLoginScreen.swift; sourceTree = ""; }; + BFBF273BC2BFB9F3EEFA988B /* CollapsibleRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleRoomTimelineView.swift; sourceTree = ""; }; + BFDCAC6CAAD65A2C24EA9C4B /* Dictionary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dictionary.swift; sourceTree = ""; }; + BFEA446F8618DBA79A9239CC /* MessageForwardingScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageForwardingScreen.swift; sourceTree = ""; }; + BFEE91FB8ABB5F5884B6D940 /* WaveformInteractionModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaveformInteractionModifier.swift; sourceTree = ""; }; + C024C151639C4E1B91FCC68B /* ElementXAttributeScope.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementXAttributeScope.swift; sourceTree = ""; }; + C070FD43DC6BF4E50217965A /* LocalizationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizationTests.swift; sourceTree = ""; }; + C08E9043618AE5B0BF7B07E1 /* TemplateScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreenViewModelTests.swift; sourceTree = ""; }; + C0900BBF0A5D5D775E917C70 /* EventBasedMessageTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBasedMessageTimelineItemProtocol.swift; sourceTree = ""; }; + C0FEA560929DD73FFEF8C3DF /* HomeScreenEmptyStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenEmptyStateView.swift; sourceTree = ""; }; + C0FF08D0BD7D0B4B6877AB7D /* SecureBackupRecoveryKeyScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupRecoveryKeyScreenViewModelTests.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 = ""; }; + C18CC37B97E77838609CFFE7 /* AdvancedSettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreen.swift; sourceTree = ""; }; + C1D737F4672021D0A7D218CD /* OIDCAccountSettingsPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OIDCAccountSettingsPresenter.swift; sourceTree = ""; }; + C1FA515B3B0D61EF1E907D2D /* BadgeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeView.swift; sourceTree = ""; }; + C258C9C815272911A5B132C3 /* FormattedBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormattedBodyText.swift; sourceTree = ""; }; + C2886615BEBAE33A0AA4D5F8 /* RoomScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenModels.swift; sourceTree = ""; }; + C2E9B841EE4878283ECDB554 /* InviteUsersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreen.swift; sourceTree = ""; }; + C2F079B5DBD0D85FEA687AAE /* SDKGeneratedMocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDKGeneratedMocks.swift; sourceTree = ""; }; + C3285BD95B564CA2A948E511 /* OnboardingFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingFlowCoordinator.swift; sourceTree = ""; }; + C33B3F17996DFDF5F0181512 /* Data.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Data.swift; sourceTree = ""; }; + C352359663A0E52BA20761EE /* LoadableImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadableImage.swift; sourceTree = ""; }; + C4756240773D26AB74C22668 /* OrientationManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrientationManagerProtocol.swift; sourceTree = ""; }; + C4C89820BB2B88D4EA28131C /* BugReportScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenViewModelProtocol.swift; sourceTree = ""; }; + C4CD503F5E0938FE53C7C6E7 /* UserDetailsEditScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDetailsEditScreenCoordinator.swift; sourceTree = ""; }; + C55679AF67545EF8087E47BE /* RoomMemberDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetails.swift; sourceTree = ""; }; + C5599255A6C98EBDA77B76E6 /* ImageRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineView.swift; sourceTree = ""; }; + C55CC239AE12339C565F6C9A /* AudioRecorderStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecorderStateTests.swift; sourceTree = ""; }; + C55D7E514F9DE4E3D72FDCAD /* SessionVerificationControllerProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationControllerProxy.swift; sourceTree = ""; }; + C5AEB5907E24092D741718AF /* ResolveVerifiedUserSendFailureScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResolveVerifiedUserSendFailureScreenCoordinator.swift; sourceTree = ""; }; + C5B7A755E985FA14469E86B2 /* RoomMembersListScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenUITests.swift; sourceTree = ""; }; + C5F06F2F09B2EDD067DC2174 /* NotificationSettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreen.swift; sourceTree = ""; }; + C616D90B1E2F033CAA325439 /* StaticLocationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticLocationScreenViewModelProtocol.swift; sourceTree = ""; }; + C618CA2B6C8758B06C88013C /* CreateRoomCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomCoordinator.swift; sourceTree = ""; }; + C687844F60BFF532D49A994C /* AnalyticsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsTests.swift; sourceTree = ""; }; + C6A9F49B3EE59147AF2F70BB /* SeparatorRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineItem.swift; sourceTree = ""; }; + C6FEA87EA3752203065ECE27 /* BugReportUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportUITests.swift; sourceTree = ""; }; + C705E605EF57C19DBE86FFA1 /* PlaceholderAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderAvatarImage.swift; 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 = ""; }; + C830A64609CBD152F06E0457 /* NotificationConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationConstants.swift; sourceTree = ""; }; + C833673B334A0651AB46F30B /* StaticLocationScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticLocationScreenViewModelTests.swift; sourceTree = ""; }; + C90514BE9B8ACCBCF0AD2489 /* ComposerToolbarViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerToolbarViewModel.swift; sourceTree = ""; }; + 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 = ""; }; + C9E535B3388755B65C34CD10 /* UnsupportedRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineView.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 = ""; }; + CA4F6D7000EDCD187E0989E7 /* PinnedEventsTimelineScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedEventsTimelineScreen.swift; sourceTree = ""; }; + CA89A2DD51B6BBE1DA55E263 /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = ""; }; + CA90BD288E5AE6BC643AFDDF /* TemplateScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreenCoordinator.swift; sourceTree = ""; }; + CACA846B3E3E9A521D98B178 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; + CAD9547E47C58930E2CE8306 /* CallScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenViewModelTests.swift; sourceTree = ""; }; + CB8D34E94AB07128DB73D6C7 /* PillConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillConstants.swift; sourceTree = ""; }; + CBBCC6E74774E79B599625D0 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; + CBF9AEA706926DD0DA2B954C /* JoinedRoomSize+MemberCount.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JoinedRoomSize+MemberCount.swift"; sourceTree = ""; }; + CC03209FDE8CE0810617BFFF /* RoomMembersListScreenMemberCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenMemberCell.swift; sourceTree = ""; }; + CC1DDB2293A51EA4C2739351 /* RoomListFiltersEmptyStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomListFiltersEmptyStateView.swift; sourceTree = ""; }; + CC437C491EA6996513B1CEAB /* ElementCallConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallConfiguration.swift; sourceTree = ""; }; + CC680E0E79D818706CB28CF8 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; + CC743C7A85E3171BCBF0A653 /* AvatarHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvatarHeaderView.swift; sourceTree = ""; }; + CCACD75595C40EACD6AD4A74 /* AuthenticationTextFieldStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationTextFieldStyle.swift; sourceTree = ""; }; + CCF71646898A2F720C5BFDF5 /* RoomDirectorySearchScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreenViewModel.swift; sourceTree = ""; }; + CD469F7513574341181F7EAA /* ServerSelectionScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionScreen.swift; sourceTree = ""; }; + CD6613DE16AD26B3A74DA1F5 /* LocationRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineItemContent.swift; sourceTree = ""; }; + 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 = ""; }; + D071F86CD47582B9196C9D16 /* UserDiscoverySection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDiscoverySection.swift; sourceTree = ""; }; + D086854995173E897F993C26 /* AdvancedSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenViewModelProtocol.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 = ""; }; + D196116D2DD3F2757D45FCB7 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/SAS.strings; sourceTree = ""; }; + D1BC84BA0AF11C2128D58ABD /* Common.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Common.swift; sourceTree = ""; }; + D1D8479BB704B7EF696F8ABE /* RoomPollsHistoryScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreenCoordinator.swift; sourceTree = ""; }; + D263254AFE5B7993FFBBF324 /* NSE.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NSE.entitlements; sourceTree = ""; }; + D26813CCE39221FE30BF22CD /* PlatformViewVersionPredicate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlatformViewVersionPredicate.swift; sourceTree = ""; }; + D28F7A6CEEA4A2815B0F0F55 /* SettingsFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsFlowCoordinator.swift; sourceTree = ""; }; + D316BB02636AF2174F2580E6 /* SoftLogoutScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutScreenViewModelProtocol.swift; sourceTree = ""; }; + 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 = ""; }; + D479DF730528153665E5782E /* RoomTimelineControllerFactoryMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerFactoryMock.swift; sourceTree = ""; }; + D49B9785E3AD7D1C15A29F2F /* MediaSourceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaSourceProxy.swift; sourceTree = ""; }; + D4DA544B2520BFA65D6DB4BB /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; + D529B976F8B2AA654D923422 /* VoiceMessageRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRoomTimelineItem.swift; sourceTree = ""; }; + D5338450E6783A576B5C16DD /* StickerRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StickerRoomTimelineView.swift; sourceTree = ""; }; + 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 = ""; }; + D66B5D86A9AB95E0E01BED82 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/InfoPlist.strings; sourceTree = ""; }; + D6DC38E64A5ED3FDB201029A /* BugReportService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportService.swift; sourceTree = ""; }; + D77B3D4950F1707E66E4A45A /* AnalyticsConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsConfiguration.swift; sourceTree = ""; }; + D77F75B3E9F99864048A422A /* DeactivateAccountScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeactivateAccountScreenViewModelTests.swift; sourceTree = ""; }; + 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 = ""; }; + D8E057FB1F07A5C201C89061 /* MockServerSelectionScreenState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockServerSelectionScreenState.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 = ""; }; + D93C94C30E3135BC9290DE13 /* VoiceMessageRecorderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecorderTests.swift; sourceTree = ""; }; + D95E8C0EFEC0C6F96EDAA71A /* PreviewTests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = PreviewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + DA14564EE143F73F7E4D1F79 /* RoomNotificationSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenModels.swift; sourceTree = ""; }; + DA2AEC1AB349A341FE13DEC1 /* StartChatScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatScreenUITests.swift; sourceTree = ""; }; + DA38899517F08FE2AF34EB45 /* MockAuthenticationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockAuthenticationService.swift; sourceTree = ""; }; + DA3D82522494E78746B2214E /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/SAS.strings; sourceTree = ""; }; + DAB8D7926A5684E18196B538 /* VoiceMessageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageCache.swift; sourceTree = ""; }; + DB06F22CFA34885B40976061 /* RoomDetailsEditScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreen.swift; sourceTree = ""; }; + DBEDCEC9D908C19C63D24395 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + DC0AEA686E425F86F6BA0404 /* UNNotification+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNNotification+Creator.swift"; sourceTree = ""; }; + DC10CCC8D68B863E20660DBC /* MessageForwardingScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageForwardingScreenViewModelProtocol.swift; sourceTree = ""; }; + DC528B3764E3CF7FCFEF40E7 /* PollInteractionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollInteractionHandler.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 = ""; }; + DE7C80EF77AD102053D3646E /* RoundedLabelItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedLabelItem.swift; sourceTree = ""; }; + DEC1D382565A4E9CAC2F14EA /* MediaFileHandleProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaFileHandleProxy.swift; sourceTree = ""; }; + DF05DA24F71B455E8EFEBC3B /* SessionVerificationViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationViewModelTests.swift; sourceTree = ""; }; + DF17EA323AD0205A6AB621AA /* Snapshotting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Snapshotting.swift; sourceTree = ""; }; + DF3D25B3EDB283B5807EADCF /* ReadMarkerRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadMarkerRoomTimelineItem.swift; sourceTree = ""; }; + DFFB0E7C6D8E190AFA0176DC /* uz */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = uz; path = uz.lproj/Localizable.stringsdict; sourceTree = ""; }; + E062C1750EFC8627DE4CAB8E /* MapTilerAuthorization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerAuthorization.swift; sourceTree = ""; }; + E06AAD6D9D3F5833E7A5A2F9 /* RoomListFilterModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomListFilterModels.swift; sourceTree = ""; }; + E0F7CCC4A9D1927223F559D5 /* AuthenticationStartScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenViewModelProtocol.swift; sourceTree = ""; }; + E0FCA0957FAA0E15A9F5579D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Untranslated.stringsdict; sourceTree = ""; }; + E0FF9CB3EFA753277291F609 /* EncryptionResetScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetScreenCoordinator.swift; sourceTree = ""; }; + E10DA51DBC8C7E1460DBCCBD /* UserProfileListRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileListRow.swift; sourceTree = ""; }; + E1573D28C8A9FB6399D0EEFB /* SecureBackupLogoutConfirmationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreenCoordinator.swift; sourceTree = ""; }; + 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 = ""; }; + E3059CFA00C67D8787273B20 /* ServerSelectionScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionScreenViewModel.swift; sourceTree = ""; }; + E321E840DCC63790049984F4 /* ElementCallServiceMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallServiceMock.swift; sourceTree = ""; }; + E34685D186453E429ADEE58E /* ClientProtocolTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientProtocolTests.swift; sourceTree = ""; }; + E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainController.swift; sourceTree = ""; }; + E3B97591B2D3D4D67553506D /* AnalyticsClientProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsClientProtocol.swift; sourceTree = ""; }; + E4103AB4340F2974D690A12A /* CallScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreen.swift; sourceTree = ""; }; + E413F4CBD7BF0588F394A9DD /* RoomDetailsEditScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenViewModel.swift; sourceTree = ""; }; + E43005941B3A2C9671E23C85 /* UserIndicatorModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorModalView.swift; sourceTree = ""; }; + E44E35AA87F49503E7B3BF6E /* AudioConverter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioConverter.swift; sourceTree = ""; }; + E461B3C8BBBFCA400B268D14 /* AppRouteURLParserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRouteURLParserTests.swift; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + E6372DD10DED30E7AD7BCE21 /* RoomListFiltersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomListFiltersView.swift; sourceTree = ""; }; + E65DA46BD5CA83747AE144F3 /* secrets.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = secrets.xcconfig; sourceTree = ""; }; + E66763BD54A3A1D9C6E6F2F1 /* PinnedItemsIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedItemsIndicatorView.swift; sourceTree = ""; }; + E6935A55AB3B0C94BC566DD6 /* EncryptionResetPasswordScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreenCoordinator.swift; sourceTree = ""; }; + E6E6BDF9D26DB05C88901416 /* RedactedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedactedRoomTimelineItem.swift; sourceTree = ""; }; + E6F5D66F158A6662F953733E /* NotificationSettingsProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsProxy.swift; sourceTree = ""; }; + E6FCC416A3BFE73DF7B3E6BF /* RoomTimelineControllerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerFactory.swift; sourceTree = ""; }; + E76A706B3EEA32B882DA5E2D /* BlockedUsersScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreenViewModelProtocol.swift; sourceTree = ""; }; + E78FC546F28E045A560F2963 /* EncryptionKeyProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionKeyProviderProtocol.swift; sourceTree = ""; }; + E8294DB9E95C0C0630418466 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; }; + E8774CF614849664B5B3C2A1 /* UserSessionFlowCoordinatorStateMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionFlowCoordinatorStateMachine.swift; sourceTree = ""; }; + E8A1BBEF7318CA6B6ACCF4AE /* AppLockSetupUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupUITests.swift; sourceTree = ""; }; + E8A1F98AE670377B20679FF5 /* MediaPlayerProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPlayerProvider.swift; sourceTree = ""; }; + E8AE4B3273BA189FDCD4055C /* UserIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicator.swift; sourceTree = ""; }; + E8CA187FE656EE5A3F6C7DE5 /* UIFont+AttributedStringBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIFont+AttributedStringBuilder.m"; sourceTree = ""; }; + E96ED747FF90332EA1333C22 /* RoomTimelineItemFixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFixtures.swift; sourceTree = ""; }; + E992D7B8BE54B2AB454613AF /* XCUIElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCUIElement.swift; sourceTree = ""; }; + E9A3D3CFA199FA7897364547 /* CallInviteRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallInviteRoomTimelineItem.swift; sourceTree = ""; }; + E9B796D347E53631576F631C /* PreviewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewTests.swift; sourceTree = ""; }; + E9D059BFE329BE09B6D96A9F /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ro; path = ro.lproj/Localizable.stringsdict; sourceTree = ""; }; + EA4D639E27D5882A6A71AECF /* GlobalSearchScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchScreenViewModelTests.swift; sourceTree = ""; }; + EA551A98778CEE7366838CE2 /* QRCodeLoginScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeLoginScreenCoordinator.swift; sourceTree = ""; }; + EA880E78AF4BD24E45A7808C /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg; path = bg.lproj/InfoPlist.strings; sourceTree = ""; }; + EAF710CB1C31F8938EAA3A7D /* RoomChangeRolesScreenSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenSection.swift; sourceTree = ""; }; + EB3B237387B8288A5A938F1B /* UserAgentBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAgentBuilderTests.swift; sourceTree = ""; }; + EB63761D9F9CE8B23CBD6179 /* PollFormScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenModels.swift; sourceTree = ""; }; + 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 = ""; }; + ECD5FCBA169B6A82F501CA1B /* AnalyticsSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenViewModelProtocol.swift; sourceTree = ""; }; + ECF79FB25E2D4BD6F50CE7C9 /* RoomMembersListScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenViewModel.swift; sourceTree = ""; }; + ED003DF1B7CF40E7073A2280 /* TracingConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracingConfiguration.swift; sourceTree = ""; }; + ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenRoomCell.swift; sourceTree = ""; }; + 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 = ""; }; + ED49073BB1C1FC649DAC2CCD /* LocationRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineView.swift; sourceTree = ""; }; + ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreen.swift; sourceTree = ""; }; + EDAA4472821985BF868CC21C /* ServerSelectionViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionViewModelTests.swift; sourceTree = ""; }; + EE378083653EF0C9B5E9D580 /* EmoteRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineItemContent.swift; sourceTree = ""; }; + EE6BFF453838CF6C3982C5A3 /* RoomDirectorySearchScreenScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreenScreenViewModelTests.swift; sourceTree = ""; }; + EEAA2832D93EC7D2608703FB /* NSEUserSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSEUserSession.swift; sourceTree = ""; }; + EEAB5662310AE73D93815134 /* JoinRoomScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinRoomScreenViewModelProtocol.swift; sourceTree = ""; }; + EF13BFD415CA84B1272E94F8 /* PINTextFieldTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PINTextFieldTests.swift; sourceTree = ""; }; + EF1593DD87F974F8509BB619 /* ElementAnimations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementAnimations.swift; sourceTree = ""; }; + EF98A02DED04075F7CF0C721 /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = id.lproj/Localizable.strings; sourceTree = ""; }; + EFF7BF82A950B91BC5469E91 /* ViewFrameReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewFrameReader.swift; sourceTree = ""; }; + EFFD3200F9960D4996159F10 /* BugReportServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportServiceTests.swift; sourceTree = ""; }; + F0096BC5DA86AF6B6E5742AC /* RoomPermissionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPermissionsTests.swift; sourceTree = ""; }; + F012CB5EE3F2B67359F6CC52 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; + F0205C03F98BE861EDABCB0D /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = be.lproj/Localizable.strings; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + 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 = ""; }; + F36C0A6D59717193F49EA986 /* UserSessionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionTests.swift; sourceTree = ""; }; + F37FA1A5D55633E1942B153B /* CallScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenCoordinator.swift; sourceTree = ""; }; + F3A1AB5A84D843B6AC8D5F1E /* AuthenticationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationService.swift; sourceTree = ""; }; + F3C7252B3461D06175D975A4 /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/SAS.strings; sourceTree = ""; }; + F3EAE3E9D5EF4A6D5D9C6CFD /* EmojiPickerScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenViewModel.swift; sourceTree = ""; }; + F4469F6AE311BDC439B3A5EC /* UserSessionMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionMock.swift; sourceTree = ""; }; + F4548A9BDE5CB3AB864BCA9F /* EffectsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EffectsView.swift; sourceTree = ""; }; + F506C6ADB1E1DA6638078E11 /* UITests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = UITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + F5311C989EC15B4C2D699025 /* StaticLocationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticLocationScreenViewModel.swift; sourceTree = ""; }; + F57C8022B8A871A1DCD1750A /* UserIndicatorToastView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorToastView.swift; sourceTree = ""; }; + F5D1BAA90F3A073D91B4F16B /* RoomNotificationSettingsProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsProxyMock.swift; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + F7478623CECC9438014244BA /* ServerConfirmationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreen.swift; sourceTree = ""; }; + F7C161B06F417CA5D1F1E088 /* WebRegistrationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebRegistrationScreenModels.swift; sourceTree = ""; }; + F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRootCoordinatorTests.swift; sourceTree = ""; }; + F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionScreenTests.swift; sourceTree = ""; }; + F8CCF9A924521DECA44778C4 /* AppLockSetupBiometricsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreen.swift; sourceTree = ""; }; + F8CEB4634C0DD7779C4AB504 /* CreateRoomScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomScreenUITests.swift; sourceTree = ""; }; + F9E543072DE58E751F028998 /* TimelineProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxy.swift; sourceTree = ""; }; + FA3EB5B1848CF4F64E63C6B7 /* PermalinkTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermalinkTests.swift; sourceTree = ""; }; + FA7BB497B2F539C17E88F6B7 /* NotificationSettingsEditScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsEditScreenViewModelProtocol.swift; sourceTree = ""; }; + FABAC5C4373B0EC24D399663 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/SAS.strings"; sourceTree = ""; }; + FB0D6CB491777E7FC6B5BA12 /* CreateRoomScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomScreen.swift; sourceTree = ""; }; + FB7BAD55A4E2B8E5828CD64C /* SoftLogoutScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutScreenViewModel.swift; sourceTree = ""; }; + FB9EABCA9348DFA27439A809 /* WaveformCursorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaveformCursorView.swift; sourceTree = ""; }; + FBB0328F2887BF0A65BC5D49 /* NotificationSettingsEditScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsEditScreen.swift; sourceTree = ""; }; + FBC776F301D374A3298C69DA /* AppCoordinatorProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCoordinatorProtocol.swift; sourceTree = ""; }; + FC83F47D2173B7538AA72E0E /* RoomSummaryProviderMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProviderMock.swift; sourceTree = ""; }; + FC853F9B4FBE039D2C16EC6B /* RoomMembersListManageMemberSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListManageMemberSheet.swift; sourceTree = ""; }; + FCE93F0CBF0D96B77111C413 /* AppLockFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockFlowCoordinator.swift; sourceTree = ""; }; + FD1275D9CE0FFBA6E8E85426 /* UserIndicatorController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorController.swift; sourceTree = ""; }; + FDB9C37196A4C79F24CE80C6 /* KeychainControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainControllerTests.swift; sourceTree = ""; }; + 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 */ + +/* Begin PBXFrameworksBuildPhase section */ + 60823A8E409E27661824D510 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + AAF0BBED840DF4A53EE85E77 /* MatrixRustSDK in Frameworks */, + E481C8FDCB6C089963C95344 /* DeviceKit in Frameworks */, + 97189E495F0E47805D1868DB /* DTCoreText in Frameworks */, + FCD3F2B82CAB29A07887A127 /* KeychainAccess in Frameworks */, + F99FB21EFC6D99D247FE7CBE /* Kingfisher in Frameworks */, + 308BD9343B95657FAA583FB7 /* SwiftState in Frameworks */, + 3F2148F11164C7C5609984EB /* GZIP in Frameworks */, + 60ED66E63A169E47489348A8 /* Sentry in Frameworks */, + EC280623A42904341363EAAF /* Collections in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BF59B36A7B2DB184B62826F6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 09713669577CDA8D012EE380 /* MatrixRustSDK in Frameworks */, + 53DEF39F0C4DE02E3FC56D91 /* KeychainAccess in Frameworks */, + F06CE9132855E81EBB6DDC32 /* Kingfisher in Frameworks */, + 67D6E0700A9C1E676F6231F8 /* Collections in Frameworks */, + D63974A88CF2BC721F109C77 /* Compound in Frameworks */, + DF05F9C9D3D977EB77E13692 /* DeviceKit in Frameworks */, + 93A549135E6C027A0D823BFE /* DTCoreText in Frameworks */, + 6F26CBC84AE87EB4068D398B /* LRUCache in Frameworks */, + 0E08BB72B2258652CF501A8B /* Version in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C68A5D5A38E20DD51CF4B4FD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7D6DC832DE7A3DE874E2E9BC /* SnapshotTesting in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CD30252A70288BD4BF476ED7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2BAA5B222856068158D0B3C6 /* MatrixRustSDK in Frameworks */, + 99ED42B8F8D6BFB1DBCF4C45 /* AnalyticsEvents in Frameworks */, + 0E8C480700870BB34A2A360F /* DeviceKit in Frameworks */, + CB498F4E27AA0545DCEF0F6F /* DTCoreText in Frameworks */, + 6832733838C57A7D3FE8FEB5 /* KeychainAccess in Frameworks */, + 2BA59D0AEFB4B82A2EC2A326 /* Kingfisher in Frameworks */, + B245583C63F8F90357B87FAE /* KZFileWatchers in Frameworks */, + A4E885358D7DD5A072A06824 /* PostHog in Frameworks */, + 29EE1791E0AFA1ABB7F23D2F /* SwiftState in Frameworks */, + 33CAC1226DFB8B5D8447D286 /* GZIP in Frameworks */, + 492274DA6691EE985C2FCCAA /* Sentry in Frameworks */, + F0F82C3C848C865C3098AA52 /* SnapshotTesting in Frameworks */, + 3A64A93A651A3CB8774ADE8E /* Collections in Frameworks */, + 3F327A62D233933F54F0F33A /* SwiftOGG in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EE878EAA342710DB973E0A87 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A70A2199394B5EC660934A5 /* MatrixRustSDK in Frameworks */, + 1F3232BD368DF430AB433907 /* Compound in Frameworks */, + F656F92A63D3DC1978D79427 /* Algorithms in Frameworks */, + 9D2E03DB175A6AB14589076D /* AnalyticsEvents in Frameworks */, + 6F2AB43A1EFAD8A97AF41A15 /* Collections in Frameworks */, + 93BA4A81B6D893271101F9F0 /* DeviceKit in Frameworks */, + 9AC5F8142413862A9E3A2D98 /* DTCoreText in Frameworks */, + CB137BFB3E083C33E398A6CB /* KeychainAccess in Frameworks */, + 3C549A0BF39F8A854D45D9FD /* Kingfisher in Frameworks */, + 41DFDD212D1BE57CA50D783B /* KZFileWatchers in Frameworks */, + 6298AB0906DDD3525CD78C6B /* LoremSwiftum in Frameworks */, + 407DCE030E0F9B7C9861D38A /* LRUCache in Frameworks */, + 8F2FAA98457750D9D664136F /* Mapbox in Frameworks */, + FC10228E73323BDC09526F97 /* PostHog in Frameworks */, + EAC6FE2CD4F50A43068ADCD8 /* SwiftState in Frameworks */, + 754602A7B2AAD443C4228ED4 /* GZIP in Frameworks */, + B0CB16349B96262AA65A04AF /* Sentry in Frameworks */, + 36AD4DD4C798E22584ED3200 /* SentrySwiftUI in Frameworks */, + 36CD6E11B37396E14F032CB6 /* Version in Frameworks */, + A0D7E5BD0298A97DCBDCE40B /* Emojibase in Frameworks */, + 44F0E1B576C7599DF8022071 /* WysiwygComposer in Frameworks */, + A93661C962B12942C08864B6 /* SwiftOGG in Frameworks */, + 37E47F5101C0C036289D3807 /* DSWaveformImageViews in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0121014DD16467736455AF16 /* VoiceMessage */ = { + isa = PBXGroup; + children = ( + DAB8D7926A5684E18196B538 /* VoiceMessageCache.swift */, + 43A84EE187D0C772E18A4E39 /* VoiceMessageCacheProtocol.swift */, + 40076C770A5FB83325252973 /* VoiceMessageMediaManager.swift */, + 889DEDD63C68ABDA8AD29812 /* VoiceMessageMediaManagerProtocol.swift */, + 26B0A96B8FE4849227945067 /* VoiceMessageRecorder.swift */, + D45C9EAA86423D7D3126DE4F /* VoiceMessageRecorderProtocol.swift */, + ); + path = VoiceMessage; + sourceTree = ""; + }; + 0210F4932B59277E2EEEF7BC /* RoomNotificationSettingsScreen */ = { + isa = PBXGroup; + children = ( + 8296D6FB451E25CEC0767BBA /* RoomNotificationSettingsScreenCoordinator.swift */, + DA14564EE143F73F7E4D1F79 /* RoomNotificationSettingsScreenModels.swift */, + 81A9B5225D0881CEFA2CF7C9 /* RoomNotificationSettingsScreenViewModel.swift */, + 03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */, + DDF77194AB6E167891D0A8F3 /* View */, + ); + path = RoomNotificationSettingsScreen; + sourceTree = ""; + }; + 0371482D36C95ABAF9D4C651 /* Recorder */ = { + isa = PBXGroup; + children = ( + 907FA4DE17DEA1A3738EFB83 /* AudioRecorder.swift */, + BBEC57C204D77908E355EF42 /* AudioRecorderProtocol.swift */, + 6569593FA36B22259E806A67 /* AudioRecorderState.swift */, + ); + path = Recorder; + sourceTree = ""; + }; + 037A5661B26EC6BE068188D7 /* Filters */ = { + isa = PBXGroup; + children = ( + E06AAD6D9D3F5833E7A5A2F9 /* RoomListFilterModels.swift */, + CC1DDB2293A51EA4C2739351 /* RoomListFiltersEmptyStateView.swift */, + E6372DD10DED30E7AD7BCE21 /* RoomListFiltersView.swift */, + 24EC819497BB5F8C4998D760 /* RoomListFilterView.swift */, + ); + path = Filters; + sourceTree = ""; + }; + 052CC920F473C10B509F9FC1 /* SwiftUI */ = { + isa = PBXGroup; + children = ( + 693E16574C6F7F9FA1015A8C /* Search.swift */, + E2DA161C142B7AB8CC40F752 /* Animation */, + CE2FBFD64A89F5DBE4EB30DB /* Layout */, + E6E1D07163F8752D62DA4A93 /* Styles */, + 10578D9852BA78D309A1CBDF /* ViewModel */, + 328DD5DA1281F758B72006C7 /* Views */, + ); + path = SwiftUI; + sourceTree = ""; + }; + 06501F0E978B2D5C92771DC7 /* Logging */ = { + isa = PBXGroup; + children = ( + 111B698739E3410E2CDB7144 /* MXLog.swift */, + 542D4F49FABA056DEEEB3400 /* RustTracing.swift */, + ED003DF1B7CF40E7073A2280 /* TracingConfiguration.swift */, + ); + path = Logging; + sourceTree = ""; + }; + 07831A7BA411CC407B4727E2 /* View */ = { + isa = PBXGroup; + children = ( + 1E49D10BFA7E4D70A947888C /* DeactivateAccountScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 0787F81684E503024BD0C051 /* Services */ = { + isa = PBXGroup; + children = ( + 4BF8D11D9ED15CFC373D0119 /* Analytics */, + 7803E03F759061C948D66B7E /* AppLock */, + FCE7249621F507F34A8122FB /* Audio */, + AAFDD509929A0CCF8BCE51EB /* Authentication */, + 0ED3F5C21537519389C07644 /* BugReport */, + 8039515BAA53B7C3275AC64A /* Client */, + 8B5E91450E85A9689931B221 /* ComposerDraft */, + 8C3BAE06B336D97DABBE2509 /* CreateRoom */, + 92E99C57D7F92ED16F73282C /* ElementCall */, + 39557ADF21345E18F3865B9E /* Emojis */, + CA555F7C7CA382ACACF0D82B /* Keychain */, + 79E560F5113ED25D172E550C /* Media */, + 6709362D60732DED2069AE0F /* MediaPlayer */, + 6DE13A7AE6587B079F4049D7 /* Notification */, + 114DC16B28140F885FD833E2 /* NotificationSettings */, + 599DFFE0805B08454E40D64A /* Polls */, + 70CC0CDA4AFDF8299C56ADE7 /* QRCode */, + 40E6246F03D1FE377BC5D963 /* Room */, + 4FFDC8D1A752384B4C6EB0EB /* RoomDirectorySearch */, + BDCEF7C3BF6D09F5611CFC8B /* SecureBackup */, + 82D5AD3EAE3A5C1068A44A88 /* Session */, + 5329E48968EB951235E83DAE /* SessionVerification */, + FCDF06BDB123505F0334B4F9 /* Timeline */, + E4E42F93A69AE52E6FAE9412 /* Users */, + CBBF6127C313A5412E438BC6 /* UserSession */, + 0121014DD16467736455AF16 /* VoiceMessage */, + ); + path = Services; + sourceTree = ""; + }; + 09C599CB430ABF160C1EE55C /* AnalyticsSettingsScreen */ = { + isa = PBXGroup; + children = ( + 4BD371B60E07A5324B9507EF /* AnalyticsSettingsScreenCoordinator.swift */, + 42C64A14EE89928207E3B42B /* AnalyticsSettingsScreenModels.swift */, + 0BCE3FAF40932AC7C7639AC4 /* AnalyticsSettingsScreenViewModel.swift */, + ECD5FCBA169B6A82F501CA1B /* AnalyticsSettingsScreenViewModelProtocol.swift */, + AAFE4295DD635085A44CBF4C /* View */, + ); + path = AnalyticsSettingsScreen; + sourceTree = ""; + }; + 0B7746360C4753B5A014838F /* SupportingFiles */ = { + isa = PBXGroup; + children = ( + 3D4DD336905C72F95EAF34B7 /* ElementX-Bridging-Header.h */, + 9C5E81214D27A6B898FC397D /* ElementX.entitlements */, + 81B17DB1BC3B0C62AF84D230 /* Info.plist */, + 048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */, + E65DA46BD5CA83747AE144F3 /* secrets.xcconfig */, + B050A6B233D95807A09289E7 /* Settings.bundle */, + F012CB5EE3F2B67359F6CC52 /* target.yml */, + ); + path = SupportingFiles; + sourceTree = ""; + }; + 0ED3F5C21537519389C07644 /* BugReport */ = { + isa = PBXGroup; + children = ( + D6DC38E64A5ED3FDB201029A /* BugReportService.swift */, + 9A68BCE6438873D2661D93D0 /* BugReportServiceProtocol.swift */, + ); + path = BugReport; + sourceTree = ""; + }; + 101EB4449E23F8A2892E4A63 /* View */ = { + isa = PBXGroup; + children = ( + CA4F6D7000EDCD187E0989E7 /* PinnedEventsTimelineScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 10578D9852BA78D309A1CBDF /* ViewModel */ = { + isa = PBXGroup; + children = ( + 6EA1D2CBAEA5D0BD00B90D1B /* BindableState.swift */, + 6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; + 109C9345160DC608877BD25C /* View */ = { + isa = PBXGroup; + children = ( + E4103AB4340F2974D690A12A /* CallScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 114DC16B28140F885FD833E2 /* NotificationSettings */ = { + isa = PBXGroup; + children = ( + 07579F9C29001E40715F3014 /* NotificationSettingsChatType.swift */, + E6F5D66F158A6662F953733E /* NotificationSettingsProxy.swift */, + 4FDD775CFD72DD2D3C8A8390 /* NotificationSettingsProxyProtocol.swift */, + C1511766C534367700C8DD75 /* RoomNotificationModeProxy.swift */, + AD6B522BD637845AB9570B10 /* RoomNotificationSettingsProxy.swift */, + E55B5EA766E89FF1F87C3ACB /* RoomNotificationSettingsProxyProtocol.swift */, + ); + path = NotificationSettings; + sourceTree = ""; + }; + 1185EECDD07495D65AC84AFC /* CallScreen */ = { + isa = PBXGroup; + children = ( + F37FA1A5D55633E1942B153B /* CallScreenCoordinator.swift */, + 28146817C61423CACCF942F5 /* CallScreenModels.swift */, + 37A63A59BFDDC494B1C20119 /* CallScreenViewModel.swift */, + AD9AD6AE5FC868962F090740 /* CallScreenViewModelProtocol.swift */, + 109C9345160DC608877BD25C /* View */, + ); + path = CallScreen; + sourceTree = ""; + }; + 13263FFEA7749D822B51AA90 /* AppLock */ = { + isa = PBXGroup; + children = ( + 3AD37D7DDF9904587601239D /* AppLockScreen */, + 4570BFC8DD6665A91381F400 /* AppLockSetupBiometricsScreen */, + 570026F1BA71A2D167652E48 /* AppLockSetupPINScreen */, + 2AC6FD695C6F79F67C056463 /* AppLockSetupSettingsScreen */, + FB039572AA54E0690B4051AD /* Common */, + ); + path = AppLock; + sourceTree = ""; + }; + 13ACE3300D6A86770E757FC0 /* View */ = { + isa = PBXGroup; + children = ( + 71A7D4DDEEE5D2CA0C8D63CD /* SoftLogoutScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 13CC0A77B6E5EEDF881C5E8B /* Supplementary */ = { + isa = PBXGroup; + children = ( + 02EE0FABA8ED6D6C1D6CE71D /* ReactionsSummaryView.swift */, + 66F91544AC136BF6477BDAB8 /* TimelineDeliveryStatusView.swift */, + 72614BFF35B8394C6E13F55A /* TimelineItemStatusView.swift */, + 54AD70D6E03D2031AE1B5A52 /* TimelineReactionsView.swift */, + 33035418BB35754232985871 /* TimelineReadReceiptsView.swift */, + ); + path = Supplementary; + sourceTree = ""; + }; + 15D44FCA9475E660B7F56DB9 /* Timeline */ = { + isa = PBXGroup; + children = ( + 2BA894BC09972DC45E497D37 /* TimelineInteractionHandler.swift */, + 029D5701F80A9AF7167BB4D0 /* TimelineModels.swift */, + 8112846C9D9D3817689CBAF8 /* TimelineTableViewController.swift */, + 97B2ACA28A854E41AE3AC9AD /* TimelineViewModel.swift */, + BB5B00A014307CE37B2812CD /* TimelineViewModelProtocol.swift */, + FDF04D0E125CB4B5C5DB5191 /* View */, + ); + path = Timeline; + sourceTree = ""; + }; + 17765802D2723FB2D9A6FF89 /* View */ = { + isa = PBXGroup; + children = ( + 89AAEA70CFF3284920811941 /* RoomChangePermissionsScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 1803CD2B96BF06009334BB61 /* PreviewTests */ = { + isa = PBXGroup; + children = ( + 21E5BB69FC9058BED96B9EFD /* Sources */, + A0D745ADE5568E50270F70EF /* SupportingFiles */, + ); + path = PreviewTests; + sourceTree = ""; + }; + 1C62F5382CC9D9F7DCEC344A /* UserDiscoveryService */ = { + isa = PBXGroup; + children = ( + 0287793F11C480E242B03DF5 /* UserDiscoveryServiceTest.swift */, + ); + path = UserDiscoveryService; + sourceTree = ""; + }; + 1CA6CD0DE6F0445156361B6D /* DeveloperOptionsScreen */ = { + isa = PBXGroup; + children = ( + 5C7C7CFA6B2A62A685FF6CE3 /* DeveloperOptionsScreenCoordinator.swift */, + 06B098A612DCB5A7358EECD5 /* DeveloperOptionsScreenModels.swift */, + 86A6F283BC574FDB96ABBB07 /* DeveloperOptionsScreenViewModel.swift */, + 54C4E7B46099462F12000C91 /* DeveloperOptionsScreenViewModelProtocol.swift */, + DF10E31B5AA21015971C3FAD /* View */, + ); + path = DeveloperOptionsScreen; + sourceTree = ""; + }; + 1E53A2E18B59B82EE3D8C23C /* View */ = { + isa = PBXGroup; + children = ( + 5A2FCA3D0F239B9E911B966B /* SecureBackupRecoveryKeyScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 21E5BB69FC9058BED96B9EFD /* Sources */ = { + isa = PBXGroup; + children = ( + 95A2E4BD7C0CAD25EF924A4C /* GeneratedPreviewTests.swift */, + E9B796D347E53631576F631C /* PreviewTests.swift */, + ); + path = Sources; + sourceTree = ""; + }; + 22F9F1514B91803BB4B88894 /* AppHooks */ = { + isa = PBXGroup; + children = ( + B6E4AB573FAEBB7B853DD04C /* AppHooks.swift */, + 2ED530A4DD98266D31E5D8E1 /* Hooks */, + ); + path = AppHooks; + sourceTree = ""; + }; + 23605DD08620BE6558242469 /* MediaUploadPreviewScreen */ = { + isa = PBXGroup; + children = ( + 74DD0855F2F76D47E5555082 /* MediaUploadPreviewScreenCoordinator.swift */, + B2E7C987AE5DC9087BB19F7D /* MediaUploadPreviewScreenModels.swift */, + 47F29139BC2A804CE5E0757E /* MediaUploadPreviewScreenViewModel.swift */, + D54E12B98252F6C527E31FEE /* MediaUploadPreviewScreenViewModelProtocol.swift */, + DD96B3F20F354494DECBC4F7 /* View */, + ); + path = MediaUploadPreviewScreen; + sourceTree = ""; + }; + 24FD174C31912A5FACFEAFB5 /* SupportingFiles */ = { + isa = PBXGroup; + children = ( + 7DDBF99755A9008CF8C8499E /* Info.plist */, + 1222DB76B917EB8A55365BA5 /* target.yml */, + CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */, + ); + path = SupportingFiles; + sourceTree = ""; + }; + 2565414373E6F68005966B8E /* SecureBackup */ = { + isa = PBXGroup; + children = ( + B1FD4FD6CEB987AE274AEEE5 /* SecureBackupKeyBackupScreen */, + 63E514D74481A3D9556DFFC3 /* SecureBackupLogoutConfirmationScreen */, + 6E8F16377AD462BBD4951271 /* SecureBackupRecoveryKeyScreen */, + 3B4C46F36A42B42C4EB14933 /* SecureBackupScreen */, + ); + path = SecureBackup; + sourceTree = ""; + }; + 25852CD5316875417111E5CA /* Progress */ = { + isa = PBXGroup; + children = ( + 97C8E13A1FBA717B0C277ECC /* ProgressCursorModifier.swift */, + 68010886142843705E342645 /* ProgressMaskModifier.swift */, + ); + path = Progress; + sourceTree = ""; + }; + 25A88085FB8D8227DCDB0C9C /* View */ = { + isa = PBXGroup; + children = ( + 1B065EC39C99C1303A101C1C /* WebRegistrationScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 26C16326BCCCED74A85A0F48 /* View */ = { + isa = PBXGroup; + children = ( + 3CFD5EB0B0EEA4549FB49784 /* SettingsScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 2774D635E78D8B98390EA694 /* Resources */ = { + isa = PBXGroup; + children = ( + 01C4C7DB37597D7D8379511A /* Assets.xcassets */, + A0C06C0F6A8621B22BFAEB56 /* Localizations */, + 8AEA6A91159FA0D3EAFCCB0D /* Sounds */, + ); + path = Resources; + sourceTree = ""; + }; + 295BCC81AB45927F5F2033B1 /* AuthenticationStartScreen */ = { + isa = PBXGroup; + children = ( + 6663BFB9FDB8752562CD12CA /* AuthenticationStartScreenCoordinator.swift */, + 8609BE4CA71C30D1FCE3AF9B /* AuthenticationStartScreenModels.swift */, + 9C3ACC093F88FD9888518561 /* AuthenticationStartScreenViewModel.swift */, + E0F7CCC4A9D1927223F559D5 /* AuthenticationStartScreenViewModelProtocol.swift */, + F3F90EBF3341F1FB47579B77 /* View */, + ); + path = AuthenticationStartScreen; + sourceTree = ""; + }; + 2AC6FD695C6F79F67C056463 /* AppLockSetupSettingsScreen */ = { + isa = PBXGroup; + children = ( + 3D9FCE4D1E3A81AC1CC5CB91 /* AppLockSetupSettingsScreenCoordinator.swift */, + 502F986D57158674172C58E3 /* AppLockSetupSettingsScreenModels.swift */, + 1D8C38663020DF2EB2D13F5E /* AppLockSetupSettingsScreenViewModel.swift */, + 8610C1D21565C950BCA6A454 /* AppLockSetupSettingsScreenViewModelProtocol.swift */, + 5C3CC0EA3D5B1E74EC71A463 /* View */, + ); + path = AppLockSetupSettingsScreen; + sourceTree = ""; + }; + 2C0F49BD446849654C0D24E0 /* RoomMember */ = { + isa = PBXGroup; + children = ( + C55679AF67545EF8087E47BE /* RoomMemberDetails.swift */, + 2F36C5D9B37E50915ECBD3EE /* RoomMemberProxy.swift */, + 32B5E17028C02DFA7DDA3931 /* RoomMemberProxyProtocol.swift */, + ); + path = RoomMember; + sourceTree = ""; + }; + 2CAAA563083EAC0FA6BDC4F3 /* View */ = { + isa = PBXGroup; + children = ( + F7478623CECC9438014244BA /* ServerConfirmationScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 2D0D49B0533C4C2EB889BF3A /* ServerSelectionScreen */ = { + isa = PBXGroup; + children = ( + D8E057FB1F07A5C201C89061 /* MockServerSelectionScreenState.swift */, + BB8BC4C791D0E88CFCF4E5DF /* ServerSelectionScreenCoordinator.swift */, + 9501D11B4258DFA33BA3B40F /* ServerSelectionScreenModels.swift */, + E3059CFA00C67D8787273B20 /* ServerSelectionScreenViewModel.swift */, + 0685156EB62D7E243F097CFC /* ServerSelectionScreenViewModelProtocol.swift */, + 36F3E6E629B4FCCA1CEE0956 /* View */, + ); + path = ServerSelectionScreen; + sourceTree = ""; + }; + 2E035B978E415C77423FA3C2 /* View */ = { + isa = PBXGroup; + children = ( + ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 2ECFF6B05DAA37EB10DBF7E8 /* UITests */ = { + isa = PBXGroup; + children = ( + 1C7F63EB1525E697CAEB002B /* BlankFormCoordinator.swift */, + 46C208DA43CE25D13E670F40 /* UITestsAppCoordinator.swift */, + EBEB8D9F4940E161B18FE4BC /* UITestsNotificationCenter.swift */, + 6CEBE5EA91E8691EDF364EC2 /* UITestsScreenIdentifier.swift */, + B7F0192CE2F891141A25B49F /* UITestsSignalling.swift */, + ); + path = UITests; + sourceTree = ""; + }; + 2ED530A4DD98266D31E5D8E1 /* Hooks */ = { + isa = PBXGroup; + children = ( + 13BE9781699FB510E9263192 /* AppSettingsHook.swift */, + 25586C0ADB814FEE9897DCAA /* BugReportHook.swift */, + 3865AD7B7249C939D7C69C33 /* CertificateValidatorHook.swift */, + 7AC0CD1CAFD3F8B057F9AEA5 /* ClientBuilderHook.swift */, + ); + path = Hooks; + sourceTree = ""; + }; + 2F2FED77226A43559F009463 /* TimelineController */ = { + isa = PBXGroup; + children = ( + 52D7074991B3267B26D89B22 /* MockRoomTimelineController.swift */, + 9F85164F9475FF2867F71AAA /* RoomTimelineController.swift */, + E6FCC416A3BFE73DF7B3E6BF /* RoomTimelineControllerFactory.swift */, + 18FE0CDF1FFA92EA7EE17B0B /* RoomTimelineControllerFactoryProtocol.swift */, + 2C0197EAE9D45A662B8847B6 /* RoomTimelineControllerProtocol.swift */, + ); + path = TimelineController; + sourceTree = ""; + }; + 2F72FD053616BA8A5D565323 /* View */ = { + isa = PBXGroup; + children = ( + 4176C3E20C772DE8D182863C /* LegalInformationScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 308FE2283B9803DBBB05602C /* Style */ = { + isa = PBXGroup; + children = ( + 1D9F148717D74F73BE724434 /* LongPressWithFeedback.swift */, + 0B0E0B55E2EE75AF67029924 /* SwipeToReplyView.swift */, + 2DA4F09CB613C54FDC73AE6A /* ThreadDecorator.swift */, + F5D8FEB1FED10E995CB002F7 /* TimelineBubbleLayout.swift */, + 1DA7E93C2E148B96EF6A8500 /* TimelineItemAccessibilityModifier.swift */, + 0A459AE4B6566B2FA99E86B2 /* TimelineItemBubbledStylerView.swift */, + 753B4C6C0EDDCBF0708DC384 /* TimelineItemSendInfoLabel.swift */, + 6CD4823EAB4B4E8BAB4F6B8C /* TimelineStyle.swift */, + 2DB0E533508094156D8024C3 /* TimelineStyler.swift */, + ); + path = Style; + sourceTree = ""; + }; + 31CE4DA53232AA534057F912 /* Mocks */ = { + isa = PBXGroup; + children = ( + 69CB8242D69B7E4D0B32E18D /* AggregatedReactionMock.swift */, + 3BAC027034248429A438886B /* AppMediatorMock.swift */, + E2F96CCBEAAA7F2185BFA354 /* ClientProxyMock.swift */, + 4E600B315B920B9687F8EE1B /* ComposerDraftServiceMock.swift */, + E321E840DCC63790049984F4 /* ElementCallServiceMock.swift */, + 1C7A6BBC686B1F840FA807FB /* EventTimelineItemSDKMock.swift */, + 867DC9530C42F7B5176BE465 /* JoinedRoomProxyMock.swift */, + 8DA1E8F287680C8ED25EDBAC /* NetworkMonitorMock.swift */, + 382B50F7E379B3DBBD174364 /* NotificationSettingsProxyMock.swift */, + B2AD8A56CD37E23071A2F4BF /* PHGPostHogMock.swift */, + D38391154120264910D19528 /* PollMock.swift */, + 894EE8F5B399A165BA2A6634 /* RoomDirectorySearchMock.swift */, + 36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */, + F5D1BAA90F3A073D91B4F16B /* RoomNotificationSettingsProxyMock.swift */, + FC83F47D2173B7538AA72E0E /* RoomSummaryProviderMock.swift */, + D479DF730528153665E5782E /* RoomTimelineControllerFactoryMock.swift */, + F74532E01B317C56C1BE8FA8 /* RoomTimelineProviderMock.swift */, + 248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */, + A4A1003A0F7A1DFB47F4E2D0 /* TimelineItemMock.swift */, + 7893780A1FD6E3F38B3E9049 /* UserIndicatorControllerMock.swift */, + AAD01F7FC2BBAC7351948595 /* UserProfile+Mock.swift */, + F4469F6AE311BDC439B3A5EC /* UserSessionMock.swift */, + B23135B06B044CB811139D2F /* Generated */, + ); + path = Mocks; + sourceTree = ""; + }; + 323160803A296713F839540B /* View */ = { + isa = PBXGroup; + children = ( + 00245D40CD90FD71D6A05239 /* EmojiPickerScreen.swift */, + 6B5E29E9A22F45534FBD5B58 /* EmojiPickerScreenHeaderView.swift */, + ); + path = View; + sourceTree = ""; + }; + 328DD5DA1281F758B72006C7 /* Views */ = { + isa = PBXGroup; + children = ( + 8F21ED7205048668BEB44A38 /* AppActivityView.swift */, + CC743C7A85E3171BCBF0A653 /* AvatarHeaderView.swift */, + 9A028783CFFF861C5E44FFB1 /* BadgeLabel.swift */, + C1FA515B3B0D61EF1E907D2D /* BadgeView.swift */, + 8CC23C63849452BC86EA2852 /* ButtonStyle.swift */, + 7EC2F1622C5BBABED6012E12 /* HeroImage.swift */, + B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */, + C352359663A0E52BA20761EE /* LoadableImage.swift */, + FFECCE59967018204876D0A5 /* LocationMarkerView.swift */, + 50E31AB0E77BB70E2BC77463 /* MatrixUserShareLink.swift */, + 648DD1C10E4957CB791FE0B8 /* OverridableAvatarImage.swift */, + C705E605EF57C19DBE86FFA1 /* PlaceholderAvatarImage.swift */, + BEF5FE93A06F563B477F024A /* RoomAvatarImage.swift */, + 7EB58E4E8D6D634C246AD5C2 /* RoomInviterLabel.swift */, + 839E2C35DF3F9C7B54C3CE49 /* RoundedCornerShape.swift */, + DE7C80EF77AD102053D3646E /* RoundedLabelItem.swift */, + AEB5FF7A09B79B0C6B528F7C /* SFNumberedListView.swift */, + E10DA51DBC8C7E1460DBCCBD /* UserProfileListRow.swift */, + ); + path = Views; + sourceTree = ""; + }; + 3348D14DBDB54E72FC67E2F3 /* MessageForwardingScreen */ = { + isa = PBXGroup; + children = ( + 06FAE373A7F20780BA84B59C /* MessageForwardingScreenCoordinator.swift */, + 52135BD9E0E7A091688F627A /* MessageForwardingScreenModels.swift */, + D8E60332509665C00179ACF6 /* MessageForwardingScreenViewModel.swift */, + DC10CCC8D68B863E20660DBC /* MessageForwardingScreenViewModelProtocol.swift */, + E816FC2BB467DD0B041C5A03 /* View */, + ); + path = MessageForwardingScreen; + sourceTree = ""; + }; + 33644C893C984570F605D94D /* View */ = { + isa = PBXGroup; + children = ( + F8CCF9A924521DECA44778C4 /* AppLockSetupBiometricsScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 336A13CA8A1DD526D9C41DD4 /* IdentityConfirmationScreen */ = { + isa = PBXGroup; + children = ( + 7A03E073077D92AA19C43DCF /* IdentityConfirmationScreenCoordinator.swift */, + 7FDF541AE914059942B575B4 /* IdentityConfirmationScreenModels.swift */, + EB76A9AFC6CCAD4998D9B045 /* IdentityConfirmationScreenViewModel.swift */, + 7C71B9802433F1B4252291BB /* IdentityConfirmationScreenViewModelProtocol.swift */, + DDC32FD8B94AA19C4FC062AD /* View */, + ); + path = IdentityConfirmationScreen; + sourceTree = ""; + }; + 337015ADFBA3AB96660DB3A6 /* Generated */ = { + isa = PBXGroup; + children = ( + 71D52BAA5BADB06E5E8C295D /* Assets.swift */, + 47EBB5D698CE9A25BB553A2D /* Strings.swift */, + B172057567E049007A5C4D92 /* Strings+SAS.swift */, + 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */, + ); + path = Generated; + sourceTree = ""; + }; + 349FE0C25B41C7AC9B7C623F /* EffectsScene */ = { + isa = PBXGroup; + children = ( + B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */, + 024F7398C5FC12586FB10E9D /* EffectsScene.swift */, + F4548A9BDE5CB3AB864BCA9F /* EffectsView.swift */, + ); + path = EffectsScene; + sourceTree = ""; + }; + 3564D09CBD6B24EA35A760B0 /* View */ = { + isa = PBXGroup; + children = ( + 1CC575D1895FA62591451A93 /* RoomMemberDetailsScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 358B1920EA0C8129198FBA4F /* View */ = { + isa = PBXGroup; + children = ( + A433BE28B40D418237BE37B5 /* ReportContentScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 36F3E6E629B4FCCA1CEE0956 /* View */ = { + isa = PBXGroup; + children = ( + CD469F7513574341181F7EAA /* ServerSelectionScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 38A1C74493B816B8753F5BC2 /* LegalInformationScreen */ = { + isa = PBXGroup; + children = ( + 5EB2CAA266B921D128C35710 /* LegalInformationScreenCoordinator.swift */, + 47873756E45B46683D97DC32 /* LegalInformationScreenModels.swift */, + 0C34667458773B02AB5FB0B2 /* LegalInformationScreenViewModel.swift */, + 8977176AB534AA41630395BC /* LegalInformationScreenViewModelProtocol.swift */, + 2F72FD053616BA8A5D565323 /* View */, + ); + path = LegalInformationScreen; + sourceTree = ""; + }; + 390C92506AD893EC593D405D /* View */ = { + isa = PBXGroup; + children = ( + 24B8177BD2AF45A286F5DA31 /* GlobalSearchScreen.swift */, + 22DB19219E6CC4D002E15D48 /* GlobalSearchScreenCell.swift */, + ); + path = View; + sourceTree = ""; + }; + 39557ADF21345E18F3865B9E /* Emojis */ = { + isa = PBXGroup; + children = ( + 3C1A3D524D63815B28FA4D62 /* EmojiCategory.swift */, + 37A243E04B58DC6E41FDCD82 /* EmojiItem.swift */, + 201305507D7DFD16E544563A /* EmojiLoaderProtocol.swift */, + 6C113E0CB7E15E9765B1817A /* EmojiProvider.swift */, + ); + path = Emojis; + sourceTree = ""; + }; + 3A2CAA4ABF5E66C3C8BBA3E9 /* Player */ = { + isa = PBXGroup; + children = ( + 7B19B2BCC779ED934E0BBC2A /* AudioPlayer.swift */, + AC9104846487244648D32C6D /* AudioPlayerProtocol.swift */, + 2BDB3E65A79779EDA5D33D8A /* AudioPlayerState.swift */, + ); + path = Player; + sourceTree = ""; + }; + 3A304097A59704AC9B869EC6 /* Helpers */ = { + isa = PBXGroup; + children = ( + B4CFE236419E830E8946639C /* Analytics+SwiftUI.swift */, + CBF9AEA706926DD0DA2B954C /* JoinedRoomSize+MemberCount.swift */, + 0B32BBA8887BD7A5C4ECF16F /* RoomModerationRole.swift */, + ); + path = Helpers; + sourceTree = ""; + }; + 3A542DF1C3BB67D829DFDC40 /* VoiceMessages */ = { + isa = PBXGroup; + children = ( + 3CCD41CD67DB5DA0D436BFE9 /* VoiceMessageRoomPlaybackView.swift */, + B70A50C41C5871B4DB905E7E /* VoiceMessageRoomTimelineView.swift */, + ); + path = VoiceMessages; + sourceTree = ""; + }; + 3AD37D7DDF9904587601239D /* AppLockScreen */ = { + isa = PBXGroup; + children = ( + 8C44BBC892499BE45B074F89 /* AppLockScreenCoordinator.swift */, + 3C3E67E09FE5A35D73818C39 /* AppLockScreenModels.swift */, + B4005D82E9D27BAF006A8FE1 /* AppLockScreenViewModel.swift */, + 08283301736A6FE9D558B2CB /* AppLockScreenViewModelProtocol.swift */, + F49710373735A3B8BB76DFF7 /* View */, + ); + path = AppLockScreen; + sourceTree = ""; + }; + 3B4C46F36A42B42C4EB14933 /* SecureBackupScreen */ = { + isa = PBXGroup; + children = ( + FDF73F49E6B6683F7E2D26F0 /* SecureBackupScreenCoordinator.swift */, + 7B3D16709ADD4F4BCC710B1E /* SecureBackupScreenModels.swift */, + 7AE094FCB6387D268C436161 /* SecureBackupScreenViewModel.swift */, + D79BB714D28C9F588DD69353 /* SecureBackupScreenViewModelProtocol.swift */, + 7478D8764F916822CD6E10AB /* View */, + ); + path = SecureBackupScreen; + sourceTree = ""; + }; + 3D733E8352DD4C461CFD8B8A /* QRCodeLoginScreen */ = { + isa = PBXGroup; + children = ( + EA551A98778CEE7366838CE2 /* QRCodeLoginScreenCoordinator.swift */, + FDEDD4D2DE0646DA724985D5 /* QRCodeLoginScreenModels.swift */, + 3BC1B7CB061C9865B2B91B56 /* QRCodeLoginScreenViewModel.swift */, + 718D8767035D37E2DB5CC550 /* QRCodeLoginScreenViewModelProtocol.swift */, + C844840F3DD48A154C65AE0C /* View */, + ); + path = QRCodeLoginScreen; + sourceTree = ""; + }; + 3E535010B850B53DDD3CFF2A /* PinnedEventsTimelineScreen */ = { + isa = PBXGroup; + children = ( + 5D53754227CEBD06358956D7 /* PinnedEventsTimelineScreenCoordinator.swift */, + 9B6572E6EF5D5F4B0C338A40 /* PinnedEventsTimelineScreenModels.swift */, + 86D7CD5CA270BFC3EBB450CA /* PinnedEventsTimelineScreenViewModel.swift */, + 510E89B989477E5EE8E503C0 /* PinnedEventsTimelineScreenViewModelProtocol.swift */, + 101EB4449E23F8A2892E4A63 /* View */, + ); + path = PinnedEventsTimelineScreen; + sourceTree = ""; + }; + 3EA31CC7012EA2A5653DAFC9 /* Fixtures */ = { + isa = PBXGroup; + children = ( + E96ED747FF90332EA1333C22 /* RoomTimelineItemFixtures.swift */, + ); + path = Fixtures; + sourceTree = ""; + }; + 3FDB9ADD4A6456674E748166 /* SupportingFiles */ = { + isa = PBXGroup; + children = ( + 748AE77AC3B0A01223033B87 /* Info.plist */, + D263254AFE5B7993FFBBF324 /* NSE.entitlements */, + 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */, + 033DB41C51865A2E83174E87 /* target.yml */, + ); + path = SupportingFiles; + sourceTree = ""; + }; + 4044C040B64B9F077298C947 /* View */ = { + isa = PBXGroup; + children = ( + E53BFB7E4F329621C844E8C3 /* AnalyticsPromptScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 405B00F139AEE3994601B36A = { + isa = PBXGroup; + children = ( + 5D26A086A8278D39B5756D6F /* project.yml */, + 99B9B46F2D621380428E68F7 /* ElementX */, + A4852B57D55D71EEBFCD931D /* UnitTests */, + C0FAC17D4DD7D3A502822550 /* UITests */, + 8A9C09B6A392465E03B8D1B1 /* IntegrationTests */, + 823ED0EC3F1B6CF47D284011 /* Tools */, + B04B538A859CD012755DC19C /* NSE */, + 1803CD2B96BF06009334BB61 /* PreviewTests */, + 681566846AF307E9BA4C72C6 /* Products */, + ); + sourceTree = ""; + }; + 40E6246F03D1FE377BC5D963 /* Room */ = { + isa = PBXGroup; + children = ( + 0E95B3BDB80531C85CD50AE6 /* InvitedRoomProxy.swift */, + 07C6B0B087FE6601C3F77816 /* JoinedRoomProxy.swift */, + B6404166CBF5CC88673FF9E2 /* RoomDetails.swift */, + 974AEAF3FE0C577A6C04AD6E /* RoomPermissions.swift */, + 47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */, + 2C0F49BD446849654C0D24E0 /* RoomMember */, + 70DABA39C844CA931B829395 /* RoomSummary */, + ); + path = Room; + sourceTree = ""; + }; + 441115752CA2408F26A72D11 /* NotificationSettingsEditScreen */ = { + isa = PBXGroup; + children = ( + AD9CB3B9DFA353AB2B7CD9F8 /* NotificationSettingsEditScreenCoordinator.swift */, + 1B564D748B67A156F413CD97 /* NotificationSettingsEditScreenModels.swift */, + 780258F1B9D15E30549FF4BE /* NotificationSettingsEditScreenViewModel.swift */, + FA7BB497B2F539C17E88F6B7 /* NotificationSettingsEditScreenViewModelProtocol.swift */, + 8081F6F9AE11BB314A838EC9 /* View */, + ); + path = NotificationSettingsEditScreen; + sourceTree = ""; + }; + 448435400B561C40E514BE1C /* FilePreviewScreen */ = { + isa = PBXGroup; + children = ( + 638A81B97D51591D0FCFA598 /* InteractiveQuickLook.swift */, + ); + path = FilePreviewScreen; + sourceTree = ""; + }; + 44B4B5DB07E5C7871873548F /* ComposerToolbar */ = { + isa = PBXGroup; + children = ( + 3A12D3D8138F1B71AFA7C858 /* CompletionSuggestionService.swift */, + 9ECF11669EF253E98AA2977A /* CompletionSuggestionServiceProtocol.swift */, + 4D3A7375AB22721C436EB056 /* ComposerToolbarModels.swift */, + C90514BE9B8ACCBCF0AD2489 /* ComposerToolbarViewModel.swift */, + B0618820D26F9871A4BBB40E /* ComposerToolbarViewModelProtocol.swift */, + 8ACEC7D7B74641FF4DB6A6D3 /* View */, + ); + path = ComposerToolbar; + sourceTree = ""; + }; + 44BBB96FAA2F0D53C507396B /* Extensions */ = { + isa = PBXGroup; + children = ( + 981663D961C94270FA035FD0 /* Alert.swift */, + 3E93A1BE7D8A2EBCAD51EEB4 /* Array.swift */, + A73A07BAEDD74C48795A996A /* AsyncSequence.swift */, + 52BD6ED18E2EB61E28C340AD /* AttributedString.swift */, + 3339B1DDB1341E833D2555BC /* AVMetadataMachineReadableCodeObject.swift */, + B6E89E530A8E92EC44301CA1 /* Bundle.swift */, + 9A1C33355FFB0F0953C35036 /* ClientBuilder.swift */, + A9FAFE1C2149E6AC8156ED2B /* Collection.swift */, + E2B1CC9AA154F4D5435BF60A /* Comparable.swift */, + 044E501B8331B339874D1B96 /* CompoundIcon.swift */, + B383DCD3DCB19E00FD478A5F /* ConfirmationDialog.swift */, + C33B3F17996DFDF5F0181512 /* Data.swift */, + 2141693488CE5446BB391964 /* Date.swift */, + BFDCAC6CAAD65A2C24EA9C4B /* Dictionary.swift */, + 7FB2253D36E81E045E1CB432 /* Duration.swift */, + 260004737C573A56FA01E86E /* Encodable.swift */, + 04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */, + 4E2245243369B99216C7D84E /* ImageCache.swift */, + 045253F9967A535EE5B16691 /* Label.swift */, + C14D83B2B7CD5501A0089EFC /* LayoutDirection.swift */, + 23AA3F4B285570805CB0CCDD /* MapTiler.swift */, + F72EFC8C634469F9262659C7 /* NSItemProvider.swift */, + 95BAC0F6C9644336E9567EE6 /* NSRegularExpresion.swift */, + 62B07B296D7A9D2F09120853 /* OrderedSet.swift */, + D26813CCE39221FE30BF22CD /* PlatformViewVersionPredicate.swift */, + 1DFE0E493FB55E5A62E7852A /* ProposedViewSize.swift */, + 7310D8DFE01AF45F0689C3AA /* Publisher.swift */, + 584A61D9C459FAFEF038A7C0 /* Section.swift */, + DF17EA323AD0205A6AB621AA /* Snapshotting.swift */, + 40B21E611DADDEF00307E7AC /* String.swift */, + A40C19719687984FD9478FBE /* Task.swift */, + 287FC98AF2664EAD79C0D902 /* UIDevice.swift */, + 05A3E8741D199CD1A37F4CBF /* UIView.swift */, + BE148A4FFEE853C5A281500C /* UNNotificationContent.swift */, + 227AC5D71A4CE43512062243 /* URL.swift */, + 2BFDCA5A09EE70BC17F2EFA7 /* URLComponents.swift */, + AE40D4A5DD857AC16EED945A /* URLSession.swift */, + 897DF5E9A70CE05A632FC8AF /* UTType.swift */, + E992D7B8BE54B2AB454613AF /* XCUIElement.swift */, + ); + path = Extensions; + sourceTree = ""; + }; + 4570BFC8DD6665A91381F400 /* AppLockSetupBiometricsScreen */ = { + isa = PBXGroup; + children = ( + 0C62E07C1164F5120727A2A8 /* AppLockSetupBiometricsScreenCoordinator.swift */, + 10F130DF775CE6BC51A4E392 /* AppLockSetupBiometricsScreenModels.swift */, + C9F893F4A111CB7BA5C96949 /* AppLockSetupBiometricsScreenViewModel.swift */, + 0CCC6C31102E1D8B9106DEDE /* AppLockSetupBiometricsScreenViewModelProtocol.swift */, + 33644C893C984570F605D94D /* View */, + ); + path = AppLockSetupBiometricsScreen; + sourceTree = ""; + }; + 459B661EA3598F9E709E81A7 /* View */ = { + isa = PBXGroup; + children = ( + 8E1584F8BCF407BB94F48F04 /* EncryptionResetPasswordScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 464C6BFAA853DC755B9C1F60 /* PinnedItemsBanner */ = { + isa = PBXGroup; + children = ( + 60C9BAE9F9436B14E4E22E8F /* PinnedItemsBannerView.swift */, + E66763BD54A3A1D9C6E6F2F1 /* PinnedItemsIndicatorView.swift */, + ); + path = PinnedItemsBanner; + sourceTree = ""; + }; + 4775A7D6FBB210BF21318AD9 /* UserDetailsEditScreen */ = { + isa = PBXGroup; + children = ( + C4CD503F5E0938FE53C7C6E7 /* UserDetailsEditScreenCoordinator.swift */, + 27D0EA07BD545CC9F234DB8D /* UserDetailsEditScreenModels.swift */, + 022E6BD64CB4610B9C95FC02 /* UserDetailsEditScreenViewModel.swift */, + 85149F56BA333619900E2410 /* UserDetailsEditScreenViewModelProtocol.swift */, + 7AE042B6E4318E352DD3991A /* View */, + ); + path = UserDetailsEditScreen; + sourceTree = ""; + }; + 490F49F5627FBEF3BB8665A3 /* SimpleScreenExample */ = { + isa = PBXGroup; + children = ( + 789DD6B31BA8BB4B3A40EF7C /* ElementX */, + 4B5DC42A1DB20ECEB0FF67CB /* Tests */, + ); + path = SimpleScreenExample; + sourceTree = ""; + }; + 493225D61FED2DA3D3B26104 /* View */ = { + isa = PBXGroup; + children = ( + C2E9B841EE4878283ECDB554 /* InviteUsersScreen.swift */, + 10F32E0B4B83D2A11EE8D011 /* InviteUsersScreenSelectedItem.swift */, + ); + path = View; + sourceTree = ""; + }; + 4AC3BA2B379A928301E21004 /* View */ = { + isa = PBXGroup; + children = ( + 4549FCB53F43DB0B278374BC /* TemplateScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 4B5DC42A1DB20ECEB0FF67CB /* Tests */ = { + isa = PBXGroup; + children = ( + AD5FCF9340D670C526AD17E4 /* UI */, + 73AB116809AE89292624CD8E /* Unit */, + ); + path = Tests; + sourceTree = ""; + }; + 4BF0F0C4AA1F62828A89099E /* View */ = { + isa = PBXGroup; + children = ( + 8F6210134203BE1F2DD5C679 /* RoomDirectoryCell.swift */, + F2E4EF80DFB8FE7C4469B15D /* RoomDirectorySearchScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 4BF8D11D9ED15CFC373D0119 /* Analytics */ = { + isa = PBXGroup; + children = ( + E3B97591B2D3D4D67553506D /* AnalyticsClientProtocol.swift */, + D77B3D4950F1707E66E4A45A /* AnalyticsConfiguration.swift */, + 57B6B383F1FD04CC0E7B60C6 /* AnalyticsConsentState.swift */, + 5445FCE0CE15E634FDC1A2E2 /* AnalyticsService.swift */, + A6B891A6DA826E2461DBB40F /* PHGPostHogConfiguration.swift */, + 5CEEAE1BFAACD6C96B6DB731 /* PHGPostHogProtocol.swift */, + 1715E3D7F53C0748AA50C91C /* PostHogAnalyticsClient.swift */, + 752A0EB49BF5BCEA37EDF7A3 /* Signposter.swift */, + 66AFD800AF033D8B0D11191A /* UserPropertiesExt.swift */, + 3A304097A59704AC9B869EC6 /* Helpers */, + ); + path = Analytics; + sourceTree = ""; + }; + 4C826614718790C58C17117F /* UnitTests */ = { + isa = PBXGroup; + children = ( + 6A8E19C4645D3F5F9FB02355 /* UnitTestsAppCoordinator.swift */, + ); + path = UnitTests; + sourceTree = ""; + }; + 4EC4EBBC4F6885775F198875 /* Sources */ = { + isa = PBXGroup; + children = ( + D33116993D54FADC0C721C1F /* Application.swift */, + D1BC84BA0AF11C2128D58ABD /* Common.swift */, + 9C4048041C1A6B20CB97FD18 /* TestMeasurementParser.swift */, + 21DD8599815136EFF5B73F38 /* UserFlowTests.swift */, + ); + path = Sources; + sourceTree = ""; + }; + 4F43EBE458FBE634996AD7C6 /* View */ = { + isa = PBXGroup; + children = ( + D7BEB970F500BFB248443FA1 /* BloomView.swift */, + B902EA6CD3296B0E10EE432B /* HomeScreen.swift */, + A3B4B58B79A6FA250B24A1EC /* HomeScreenContent.swift */, + C0FEA560929DD73FFEF8C3DF /* HomeScreenEmptyStateView.swift */, + D8FC33C3F6BF597E095CE9FA /* HomeScreenInviteCell.swift */, + 05512FB13987D221B7205DE0 /* HomeScreenRecoveryKeyConfirmationBanner.swift */, + ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */, + C7661EFFCAA307A97D71132A /* HomeScreenRoomList.swift */, + 4691B8DE1D51DE152680098A /* HomeScreenSlidingSyncMigrationBanner.swift */, + 84AF32E4136FD6F159D86C2C /* RoomDirectorySearchView.swift */, + 037A5661B26EC6BE068188D7 /* Filters */, + ); + path = View; + sourceTree = ""; + }; + 4FFDC8D1A752384B4C6EB0EB /* RoomDirectorySearch */ = { + isa = PBXGroup; + children = ( + 471BB7276C97AF60B3A5463B /* RoomDirectorySearchProxy.swift */, + 0516C69708D5CBDE1A8E77EC /* RoomDirectorySearchProxyProtocol.swift */, + ); + path = RoomDirectorySearch; + sourceTree = ""; + }; + 505AE6F89590187813390D12 /* ItemMenu */ = { + isa = PBXGroup; + children = ( + A243A6E6207297123E60DE48 /* TimelineItemMacContextMenu.swift */, + 91FFE1F410969ECB23FE9BB2 /* TimelineItemMenu.swift */, + 6F1C3CBBC62C566DDF5E84C1 /* TimelineItemMenuAction.swift */, + A9E6065FC6BC4A1B4C629E08 /* TimelineItemMenuActionProvider.swift */, + ); + path = ItemMenu; + sourceTree = ""; + }; + 52AA75722911233E40A3B366 /* Scripts */ = { + isa = PBXGroup; + children = ( + 9A5AE840145B5AB195A3B186 /* Templates */, + ); + path = Scripts; + sourceTree = ""; + }; + 53280D2292E6C9C7821773FD /* UserSession */ = { + isa = PBXGroup; + children = ( + F36C0A6D59717193F49EA986 /* UserSessionTests.swift */, + ); + path = UserSession; + sourceTree = ""; + }; + 5329E48968EB951235E83DAE /* SessionVerification */ = { + isa = PBXGroup; + children = ( + C55D7E514F9DE4E3D72FDCAD /* SessionVerificationControllerProxy.swift */, + 1D56469A9EE0CFA2B7BA9760 /* SessionVerificationControllerProxyProtocol.swift */, + ); + path = SessionVerification; + sourceTree = ""; + }; + 53FB148CD26AFB6A5B9E20B3 /* BugReportScreen */ = { + isa = PBXGroup; + children = ( + A3FBD9C2B9A5479526920399 /* BugReportScreenCoordinator.swift */, + 51C2BCE0BC1FC69C1B36E688 /* BugReportScreenModels.swift */, + 303FCADE77DF1F3670C086ED /* BugReportScreenViewModel.swift */, + C4C89820BB2B88D4EA28131C /* BugReportScreenViewModelProtocol.swift */, + A151229F1A2347F37558496A /* View */, + ); + path = BugReportScreen; + sourceTree = ""; + }; + 566F2B84465726112B830CF6 /* Other */ = { + isa = PBXGroup; + children = ( + 4959CECEC984B3995616F427 /* DataProtectionManager.swift */, + D3D455BC2423D911A62ACFB2 /* NSELogger.swift */, + EEAA2832D93EC7D2608703FB /* NSEUserSession.swift */, + 49E751D7EDB6043238111D90 /* UNNotificationRequest.swift */, + ); + path = Other; + sourceTree = ""; + }; + 570026F1BA71A2D167652E48 /* AppLockSetupPINScreen */ = { + isa = PBXGroup; + children = ( + 1FAF8C2226A57B9AB7446B31 /* AppLockSetupPINScreenCoordinator.swift */, + B410B32B72C90BF94E481F33 /* AppLockSetupPINScreenModels.swift */, + A019A12C866D64CF072024B9 /* AppLockSetupPINScreenViewModel.swift */, + B7884BD256C091EB511B2EDF /* AppLockSetupPINScreenViewModelProtocol.swift */, + AC24CD8D1E51188678C6AE07 /* View */, + ); + path = AppLockSetupPINScreen; + sourceTree = ""; + }; + 593C7129C5927E25AD8B688F /* FlowCoordinators */ = { + isa = PBXGroup; + children = ( + FCE93F0CBF0D96B77111C413 /* AppLockFlowCoordinator.swift */, + 0DBB08A95EFA668F2CF27211 /* AppLockSetupFlowCoordinator.swift */, + A9B069D7772DDF6513E0F1B8 /* AuthenticationFlowCoordinator.swift */, + 7367B3B9A8CAF902220F31D1 /* BugReportFlowCoordinator.swift */, + C3285BD95B564CA2A948E511 /* OnboardingFlowCoordinator.swift */, + A54AAF72E821B4084B7E4298 /* PinnedEventsTimelineFlowCoordinator.swift */, + 9A008E57D52B07B78DFAD1BB /* RoomFlowCoordinator.swift */, + 0833F51229E166BCA141D004 /* RoomRolesAndPermissionsFlowCoordinator.swift */, + D28F7A6CEEA4A2815B0F0F55 /* SettingsFlowCoordinator.swift */, + C99FDEEB71173C4C6FA2734C /* UserSessionFlowCoordinator.swift */, + E8774CF614849664B5B3C2A1 /* UserSessionFlowCoordinatorStateMachine.swift */, + ); + path = FlowCoordinators; + sourceTree = ""; + }; + 5970F275D6014548DCED6106 /* ReportContentScreen */ = { + isa = PBXGroup; + children = ( + A16CD2C62CB7DB78A4238485 /* ReportContentScreenCoordinator.swift */, + 3CCE3636E3D01477C8B2E9D0 /* ReportContentScreenModels.swift */, + 81B17B1F29448D1B9049B11C /* ReportContentScreenViewModel.swift */, + 713B48DBF65DE4B0DD445D66 /* ReportContentScreenViewModelProtocol.swift */, + 358B1920EA0C8129198FBA4F /* View */, + ); + path = ReportContentScreen; + sourceTree = ""; + }; + 599DFFE0805B08454E40D64A /* Polls */ = { + isa = PBXGroup; + children = ( + DC528B3764E3CF7FCFEF40E7 /* PollInteractionHandler.swift */, + 259E5B05BDE6E20C26CF11B4 /* PollInteractionHandlerProtocol.swift */, + ); + path = Polls; + sourceTree = ""; + }; + 5AD98DB6E142A4A4A2D8BA2D /* View */ = { + isa = PBXGroup; + children = ( + 6B2A421198FD20AAAED20004 /* RoomChangeRolesScreen.swift */, + 23E6EB7960BC9D0F7396B3BD /* RoomChangeRolesScreenRow.swift */, + EAF710CB1C31F8938EAA3A7D /* RoomChangeRolesScreenSection.swift */, + 3D9B45D584D232CB9E5C7734 /* RoomChangeRolesScreenSelectedItem.swift */, + ); + path = View; + sourceTree = ""; + }; + 5B2C520AB9863B8CBC8EB3CA /* SoftLogoutScreen */ = { + isa = PBXGroup; + children = ( + 5644919DB2022397D9D5825A /* MockSoftLogoutScreenState.swift */, + 05596E4A11A8C9346E9E54AE /* SoftLogoutScreenCoordinator.swift */, + 2BB385E148DE55C85C0A02D6 /* SoftLogoutScreenModels.swift */, + FB7BAD55A4E2B8E5828CD64C /* SoftLogoutScreenViewModel.swift */, + D316BB02636AF2174F2580E6 /* SoftLogoutScreenViewModelProtocol.swift */, + 13ACE3300D6A86770E757FC0 /* View */, + ); + path = SoftLogoutScreen; + sourceTree = ""; + }; + 5C3CC0EA3D5B1E74EC71A463 /* View */ = { + isa = PBXGroup; + children = ( + 5484457C81B325660901B161 /* AppLockSetupSettingsScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 5DC032EC5F19009AA7CADB41 /* View */ = { + isa = PBXGroup; + children = ( + E1A5FEF17ED7E6176D922D4F /* RoomDetailsScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 5F6CB68B44F6C587E463A934 /* View */ = { + isa = PBXGroup; + children = ( + DB06F22CFA34885B40976061 /* RoomDetailsEditScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 605F8221E52991786397FCC9 /* View */ = { + isa = PBXGroup; + children = ( + 4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 63E514D74481A3D9556DFFC3 /* SecureBackupLogoutConfirmationScreen */ = { + isa = PBXGroup; + children = ( + E1573D28C8A9FB6399D0EEFB /* SecureBackupLogoutConfirmationScreenCoordinator.swift */, + DCF239C619971FDE48132550 /* SecureBackupLogoutConfirmationScreenModels.swift */, + 7DC017C3CB6B0F7C63F460F2 /* SecureBackupLogoutConfirmationScreenViewModel.swift */, + 74E08B8A66948E9690F38B94 /* SecureBackupLogoutConfirmationScreenViewModelProtocol.swift */, + FB4987F1C660F2085258866B /* View */, + ); + path = SecureBackupLogoutConfirmationScreen; + sourceTree = ""; + }; + 6709362D60732DED2069AE0F /* MediaPlayer */ = { + isa = PBXGroup; + children = ( + FE87C931165F5E201CACBB87 /* MediaPlayerProtocol.swift */, + E8A1F98AE670377B20679FF5 /* MediaPlayerProvider.swift */, + F5E23D8EE6CBACF32F1EC874 /* MediaPlayerProviderProtocol.swift */, + ); + path = MediaPlayer; + sourceTree = ""; + }; + 6765932445C053E15E63C29A /* SupportingFiles */ = { + isa = PBXGroup; + children = ( + 1059E2AE7878CF7820592637 /* Info.plist */, + 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */, + 536E72DCBEEC4A1FE66CFDCE /* target.yml */, + ); + path = SupportingFiles; + sourceTree = ""; + }; + 6792D400AF30A6F2ACD426E4 /* View */ = { + isa = PBXGroup; + children = ( + 869A8A4632E511351BFE2EC4 /* JoinRoomScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 679E9837ECA8D6776079D16E /* RoomScreen */ = { + isa = PBXGroup; + children = ( + B8108C8F0ACF6A7EB72D0117 /* RoomScreenCoordinator.swift */, + C2886615BEBAE33A0AA4D5F8 /* RoomScreenModels.swift */, + 9CE3C90E487B255B735D73C8 /* RoomScreenViewModel.swift */, + A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */, + 44B4B5DB07E5C7871873548F /* ComposerToolbar */, + 79023E5904B155E8E2B8B502 /* View */, + ); + path = RoomScreen; + sourceTree = ""; + }; + 681566846AF307E9BA4C72C6 /* Products */ = { + isa = PBXGroup; + children = ( + 4CD6AC7546E8D7E5C73CEA48 /* ElementX.app */, + 9C7F7DE62D33C6A26CBFCD72 /* IntegrationTests.xctest */, + 0D8F620C8B314840D8602E3F /* NSE.appex */, + D95E8C0EFEC0C6F96EDAA71A /* PreviewTests.xctest */, + F506C6ADB1E1DA6638078E11 /* UITests.xctest */, + AAC9344689121887B74877AF /* UnitTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 6B0910BCE4F1B02F124E1A09 /* TimelineItemContent */ = { + isa = PBXGroup; + children = ( + B858A61F2A570DFB8DE570A7 /* AggregratedReaction.swift */, + 96C4762F8D6112E43117DB2F /* CustomStringConvertible.swift */, + 955336CBD5ED73C792D1F580 /* EncryptionAuthenticity.swift */, + 314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */, + 5DE8D25D6A91030175D52A20 /* RoomTimelineItemProperties.swift */, + BE89A8BD65CCE3FCC925CA14 /* TimelineItemReplyDetails.swift */, + ); + path = TimelineItemContent; + sourceTree = ""; + }; + 6C708A9F46EDE1105C640335 /* DeactivateAccountScreen */ = { + isa = PBXGroup; + children = ( + 8A1009E4A78F86DA42E1EAF0 /* DeactivateAccountScreenCoordinator.swift */, + BE78CAD0B964C66FD06EF83E /* DeactivateAccountScreenModels.swift */, + 2AC3FDB58F57386741A4FC7F /* DeactivateAccountScreenViewModel.swift */, + 82EE3B877D91030248B1242D /* DeactivateAccountScreenViewModelProtocol.swift */, + 07831A7BA411CC407B4727E2 /* View */, + ); + path = DeactivateAccountScreen; + sourceTree = ""; + }; + 6D7503E64A458DD09E65A3F7 /* View */ = { + isa = PBXGroup; + children = ( + 307702DD66E7DDCDD9214784 /* IdentityConfirmedScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 6DE13A7AE6587B079F4049D7 /* Notification */ = { + isa = PBXGroup; + children = ( + C830A64609CBD152F06E0457 /* NotificationConstants.swift */, + 6EE5E2BBFBC7947CFE789B4D /* Manager */, + 832FC81F760220239E285294 /* Proxy */, + ); + path = Notification; + sourceTree = ""; + }; + 6E8F16377AD462BBD4951271 /* SecureBackupRecoveryKeyScreen */ = { + isa = PBXGroup; + children = ( + 596AA8843AC1A234F3387767 /* SecureBackupRecoveryKeyScreenCoordinator.swift */, + 645E027C112740573D27765C /* SecureBackupRecoveryKeyScreenModels.swift */, + 7061BE2C0BF427C38AEDEF5E /* SecureBackupRecoveryKeyScreenViewModel.swift */, + 93E7304F5ECB4CB11CB10E60 /* SecureBackupRecoveryKeyScreenViewModelProtocol.swift */, + 1E53A2E18B59B82EE3D8C23C /* View */, + ); + path = SecureBackupRecoveryKeyScreen; + sourceTree = ""; + }; + 6EE5E2BBFBC7947CFE789B4D /* Manager */ = { + isa = PBXGroup; + children = ( + 94D670124FC3E84F23A62CCF /* APNSPayload.swift */, + 1423AB065857FA546444DB15 /* NotificationManager.swift */, + A057F2FDC14866C3026A89A4 /* NotificationManagerProtocol.swift */, + 45D8149FDDA0315CDC553B4B /* UserNotificationCenterProtocol.swift */, + ); + path = Manager; + sourceTree = ""; + }; + 703929219780FFABAC6380AA /* Windowing */ = { + isa = PBXGroup; + children = ( + C4756240773D26AB74C22668 /* OrientationManagerProtocol.swift */, + 5A37E2FACFD041CE466223CD /* SceneDelegate.swift */, + 035177BCD8E8308B098AC3C2 /* WindowManager.swift */, + 06F27F588F9059128E17C669 /* WindowManagerProtocol.swift */, + ); + path = Windowing; + sourceTree = ""; + }; + 70B74A432C241E56A7ACE610 /* Settings */ = { + isa = PBXGroup; + children = ( + EB5B1119B5AD79297F1D49EB /* AccountSettings */, + 09C599CB430ABF160C1EE55C /* AnalyticsSettingsScreen */, + 7563BA5BBB57C5520C067859 /* AvancedOptionsScreen */, + 1CA6CD0DE6F0445156361B6D /* DeveloperOptionsScreen */, + 38A1C74493B816B8753F5BC2 /* LegalInformationScreen */, + 441115752CA2408F26A72D11 /* NotificationSettingsEditScreen */, + 7B91CB64534AD870924CCFEF /* NotificationSettingsScreen */, + B364E08924AD15820350CDD9 /* SettingsScreen */, + 4775A7D6FBB210BF21318AD9 /* UserDetailsEditScreen */, + ); + path = Settings; + sourceTree = ""; + }; + 70C5B842301AC281DF374E41 /* Extensions */ = { + isa = PBXGroup; + children = ( + 60F18AECC9D38C2B6D85F99C /* Publisher.swift */, + 74611A4182DCF5F4D42696EC /* XCTestCase.swift */, + ); + path = Extensions; + sourceTree = ""; + }; + 70CC0CDA4AFDF8299C56ADE7 /* QRCode */ = { + isa = PBXGroup; + children = ( + B4427AF4B7FB7EF3E3D424C7 /* QRCodeLoginService.swift */, + 536C0E2178949B290776EA4E /* QRCodeLoginServiceProtocol.swift */, + ); + path = QRCode; + sourceTree = ""; + }; + 70DABA39C844CA931B829395 /* RoomSummary */ = { + isa = PBXGroup; + children = ( + B0A307A44F952CD73E63AE31 /* RoomEventStringBuilder.swift */, + 80E815FF3CC5E5A355E3A25E /* RoomMessageEventStringBuilder.swift */, + 29A953B6C0C431DBF4DD00B4 /* RoomSummary.swift */, + CDB3227C7A74B734924942E9 /* RoomSummaryProvider.swift */, + 10CC626F97AD70FF0420C115 /* RoomSummaryProviderProtocol.swift */, + ); + path = RoomSummary; + sourceTree = ""; + }; + 73AB116809AE89292624CD8E /* Unit */ = { + isa = PBXGroup; + children = ( + C08E9043618AE5B0BF7B07E1 /* TemplateScreenViewModelTests.swift */, + ); + path = Unit; + sourceTree = ""; + }; + 73CD9796729EB702B4DFA88C /* Sources */ = { + isa = PBXGroup; + children = ( + 58C2527813FDAE23E72A9063 /* AnalyticsSettingsScreenViewModelTests.swift */, + C687844F60BFF532D49A994C /* AnalyticsTests.swift */, + E461B3C8BBBFCA400B268D14 /* AppRouteURLParserTests.swift */, + 893777A4997BBDB68079D4F5 /* ArrayTests.swift */, + AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */, + 37CA26F55123E36B50DB0B3A /* AttributedStringTests.swift */, + 89233612A8632AD7E2803620 /* AudioPlayerStateTests.swift */, + C55CC239AE12339C565F6C9A /* AudioRecorderStateTests.swift */, + 2441E2424E78A40FC95DBA76 /* AudioRecorderTests.swift */, + 8FB89DC7F9A4A91020037001 /* AuthenticationStartScreenViewModelTests.swift */, + 93E1FF0DFBB3768F79FDBF6D /* AVMetadataMachineReadableCodeObjectExtensionsTest.swift */, + 240610DF32F3213BEC5611D7 /* BlockedUsersScreenViewModelTests.swift */, + 7EECE8B331CD169790EF284F /* BugReportScreenViewModelTests.swift */, + EFFD3200F9960D4996159F10 /* BugReportServiceTests.swift */, + CAD9547E47C58930E2CE8306 /* CallScreenViewModelTests.swift */, + E34685D186453E429ADEE58E /* ClientProtocolTests.swift */, + D5EA0312A6262484AA393AC9 /* CompletionSuggestionServiceTests.swift */, + CA29952595B804DA221A0C1D /* ComposerToolbarViewModelTests.swift */, + 69D42EE0102D2857933625DD /* CreateRoomViewModelTests.swift */, + 3B5E97E9615A158C76B2AB77 /* DateTests.swift */, + D77F75B3E9F99864048A422A /* DeactivateAccountScreenViewModelTests.swift */, + 6D0A27607AB09784C8501B5C /* DeveloperOptionsScreenViewModelTests.swift */, + A58E93D91DE3288010390DEE /* EmojiDetectionTests.swift */, + 099F2D36C141D845A445B1E6 /* EmojiProviderTests.swift */, + 84B7A28A6606D58D1E38C55A /* ExpiringTaskRunnerTests.swift */, + 1A7ED2EF5BDBAD2A7DBC4636 /* GeoURITests.swift */, + EA4D639E27D5882A6A71AECF /* GlobalSearchScreenViewModelTests.swift */, + B73587C2E3CF5998361AE516 /* HomeScreenRoomTests.swift */, + 505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */, + 845DDBDE5A0887E73D38B826 /* InviteUsersViewModelTests.swift */, + DE5127D6EA05B2E45D0A7D59 /* JoinRoomScreenViewModelTests.swift */, + FDB9C37196A4C79F24CE80C6 /* KeychainControllerTests.swift */, + 6E5725BC6C63604CB769145B /* LegalInformationScreenViewModelTests.swift */, + C070FD43DC6BF4E50217965A /* LocalizationTests.swift */, + 3DC1943ADE6A62ED5129D7C8 /* LoggingTests.swift */, + A05707BF550D770168A406DB /* LoginViewModelTests.swift */, + 376D941BF8BB294389C0DE24 /* MapTilerURLBuildersTests.swift */, + F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */, + 2D7A2C4A3A74F0D2FFE9356A /* MediaPlayerProviderTests.swift */, + AE203026B9AD3DB412439866 /* MediaUploadingPreprocessorTests.swift */, + 03FABD73FD8086EFAB699F42 /* MediaUploadPreviewScreenViewModelTests.swift */, + 6F6E6EDC4BBF962B2ED595A4 /* MessageForwardingScreenViewModelTests.swift */, + F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */, + 78913D6E120D46138E97C107 /* NavigationSplitCoordinatorTests.swift */, + 9C698E30698EC59302A8EEBD /* NavigationStackCoordinatorTests.swift */, + 8544F7058D31DBEB8DBFF0F5 /* NotificationSettingsEditScreenViewModelTests.swift */, + 514363244AE7D68080D44C6F /* NotificationSettingsScreenViewModelTests.swift */, + FA3EB5B1848CF4F64E63C6B7 /* PermalinkTests.swift */, + 31A6314FDC51DA25712D9A81 /* PillContextTests.swift */, + 6FA38E813BE14149F173F461 /* PinnedEventsBannerStateTests.swift */, + 347D708104CCEF771428C9A3 /* PollFormScreenViewModelTests.swift */, + 25E7E9B7FEAB6169D960C206 /* QRCodeLoginScreenViewModelTests.swift */, + 086C19086DD16E9B38E25954 /* ReportContentViewModelTests.swift */, + 57084488B03BDB33C7B7CA0E /* ResolveVerifiedUserSendFailureScreenViewModelTests.swift */, + A7978C9EFBDD7DE39BD86726 /* RestorationTokenTests.swift */, + 41D041A857614A9AE13C7795 /* RoomChangePermissionsScreenViewModelTests.swift */, + 8F841F219ACDFC1D3F42FEFB /* RoomChangeRolesScreenViewModelTests.swift */, + 00E5B2CBEF8F96424F095508 /* RoomDetailsEditScreenViewModelTests.swift */, + 2EFE1922F39398ABFB36DF3F /* RoomDetailsViewModelTests.swift */, + EE6BFF453838CF6C3982C5A3 /* RoomDirectorySearchScreenScreenViewModelTests.swift */, + 4FCB2126C091EEF2454B4D56 /* RoomFlowCoordinatorTests.swift */, + 8AE0C9653870803E4F91F474 /* RoomListFiltersStateTests.swift */, + EC589E641AE46EFB2962534D /* RoomMemberDetailsViewModelTests.swift */, + 3E9E0929CEFA356090BE5FB8 /* RoomMembersListScreenViewModelTests.swift */, + 58D295F0081084F38DB20893 /* RoomNotificationSettingsScreenViewModelTests.swift */, + F0096BC5DA86AF6B6E5742AC /* RoomPermissionsTests.swift */, + B40233F2989AD49906BB310D /* RoomPollsHistoryScreenViewModelTests.swift */, + 48FEFF746DB341CDB18D7AAA /* RoomRolesAndPermissionsScreenViewModelTests.swift */, + 93CF7B19FFCF8EFBE0A8696A /* RoomScreenViewModelTests.swift */, + AEEAFB646E583655652C3D04 /* RoomStateEventStringBuilderTests.swift */, + 046C0D3F53B0B5EF0A1F5BEA /* RoomSummaryTests.swift */, + 2E88534A39781D76487D59DF /* SecureBackupKeyBackupScreenViewModelTests.swift */, + 848F69921527D31CAACB93AF /* SecureBackupLogoutConfirmationScreenViewModelTests.swift */, + C0FF08D0BD7D0B4B6877AB7D /* SecureBackupRecoveryKeyScreenViewModelTests.swift */, + 40316EFFEAC7B206EE9A55AE /* SecureBackupScreenViewModelTests.swift */, + 277C20CDD5B64510401B6D0D /* ServerConfigurationScreenViewStateTests.swift */, + F08776C48FFB47CACF64ED10 /* ServerConfirmationScreenViewModelTests.swift */, + EDAA4472821985BF868CC21C /* ServerSelectionViewModelTests.swift */, + 0825EAFD47332DD459DE893F /* SessionDirectoriesTests.swift */, + A1C22B1B5FA3A765EADB2CC9 /* SessionVerificationStateMachineTests.swift */, + DF05DA24F71B455E8EFEBC3B /* SessionVerificationViewModelTests.swift */, + 3D487C1185D658F8B15B8F55 /* SettingsViewModelTests.swift */, + 32C5DAA1773F57653BF1C4F9 /* SoftLogoutViewModelTests.swift */, + 6DF438EAFC732D2D95D34BF6 /* StartChatViewModelTests.swift */, + C833673B334A0651AB46F30B /* StaticLocationScreenViewModelTests.swift */, + 2CEBCB9676FCD1D0F13188DD /* StringTests.swift */, + 2AB2C848BB9A7A9B618B7B89 /* TextBasedRoomTimelineTests.swift */, + 9AA3AF94A06D319BB37E52DA /* TimelineItemFactoryTests.swift */, + 6509708F54FC883604DFDC95 /* TimelineViewModelTests.swift */, + 1734A445A58ED855B977A0A8 /* TracingConfigurationTests.swift */, + 76310030C831D4610A705603 /* URLComponentsTests.swift */, + EB3B237387B8288A5A938F1B /* UserAgentBuilderTests.swift */, + 2429224EB0EEA34D35CE9249 /* UserIndicatorControllerTests.swift */, + BA241DEEF7C8A7181C0AEDC9 /* UserPreferenceTests.swift */, + 71E2E5103702D13361D09100 /* UserProfileScreenViewModelTests.swift */, + 4FA29BAE9B0F2D90E57B261C /* UserSessionFlowCoordinatorTests.swift */, + 283974987DA7EC61D2AB57D9 /* VoiceMessageCacheTests.swift */, + AC4F10BDD56FA77FEC742333 /* VoiceMessageMediaManagerTests.swift */, + D93C94C30E3135BC9290DE13 /* VoiceMessageRecorderTests.swift */, + 53280D2292E6C9C7821773FD /* UserSession */, + 9613851C68D8C01EABFB3569 /* AppLock */, + 70C5B842301AC281DF374E41 /* Extensions */, + A6AA0A048CAE428A5CA4CBBB /* LayoutTests */, + 7583EAC171059A86B767209F /* MediaProvider */, + 7DBC911559934065993A5FF4 /* NotificationManager */, + 1C62F5382CC9D9F7DCEC344A /* UserDiscoveryService */, + ); + path = Sources; + sourceTree = ""; + }; + 73E032ADD008D63812791D97 /* LogViewerScreen */ = { + isa = PBXGroup; + children = ( + A84D413BF49F0E980F010A6B /* LogViewerScreenCoordinator.swift */, + 01B795AAAB7B8747FE2FF311 /* LogViewerScreenModels.swift */, + 0BB05221D7D941CC82DC8480 /* LogViewerScreenViewModel.swift */, + 7463464054DDF194C54F0B04 /* LogViewerScreenViewModelProtocol.swift */, + 786BF682AB6BA65DC8F53D3D /* View */, + ); + path = LogViewerScreen; + sourceTree = ""; + }; + 7431C962E314ADAE38B6D708 /* Analytics */ = { + isa = PBXGroup; + children = ( + 196004E7695FBA292A7944AF /* ScreenTrackerViewModifier.swift */, + ); + path = Analytics; + sourceTree = ""; + }; + 7478D8764F916822CD6E10AB /* View */ = { + isa = PBXGroup; + children = ( + 84A00BB9CD12CF6AC98D5485 /* SecureBackupScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 7563BA5BBB57C5520C067859 /* AvancedOptionsScreen */ = { + isa = PBXGroup; + children = ( + 7E492690C8B27A892C194CC4 /* AdvancedSettingsScreenCoordinator.swift */, + 4999B5FD50AED7CB0F590FF8 /* AdvancedSettingsScreenModels.swift */, + B63B69F9A2BC74DD40DC75C8 /* AdvancedSettingsScreenViewModel.swift */, + D086854995173E897F993C26 /* AdvancedSettingsScreenViewModelProtocol.swift */, + B8DF5C80CDA495A1E5ED20D9 /* View */, + ); + path = AvancedOptionsScreen; + sourceTree = ""; + }; + 7583EAC171059A86B767209F /* MediaProvider */ = { + isa = PBXGroup; + children = ( + 3EF1AC723C2609C7705569CA /* MediaLoaderTests.swift */, + 62A81CCC2516D9CF9322DF01 /* MediaProviderTests.swift */, + AC1DA29A5A041CC0BACA7CB0 /* MockImageCache.swift */, + ); + path = MediaProvider; + sourceTree = ""; + }; + 75D1D02F7F3AC1122FCFB4F3 /* Items */ = { + isa = PBXGroup; + children = ( + 8428BD1821586CEE0B9C9ECA /* Messages */, + B1FC81662045E2369B0C4A0E /* Other */, + D977D4E565C06D3F41C8F8FC /* Virtual */, + ); + path = Items; + sourceTree = ""; + }; + 7803E03F759061C948D66B7E /* AppLock */ = { + isa = PBXGroup; + children = ( + 851B95BB98649B8E773D6790 /* AppLockService.swift */, + 26EAAB54C6CE91D64B69A9F8 /* AppLockServiceProtocol.swift */, + 490BEADEFB2D6B7C9F618AE8 /* AppLockTimer.swift */, + 1BA5A62DA4B543827FF82354 /* LAContextMock.swift */, + ); + path = AppLock; + sourceTree = ""; + }; + 780F74C73E826685A9DB289B /* Navigation */ = { + isa = PBXGroup; + children = ( + 27A9E3FBE8A66B5A17AD7F74 /* AppRoutes.swift */, + B8F28602AC7AC881AED37EBA /* NavigationCoordinators.swift */, + 9A22A05E472533ED3C5A31B3 /* NavigationModule.swift */, + CA28F29C9F93E93CC3C2C715 /* NavigationRootCoordinator.swift */, + ); + path = Navigation; + sourceTree = ""; + }; + 786BF682AB6BA65DC8F53D3D /* View */ = { + isa = PBXGroup; + children = ( + 5A07692536D66E3DA32C4964 /* LogViewerScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 78915D878159D302395D57BF /* SupportingFiles */ = { + isa = PBXGroup; + children = ( + 49D2C8E66E83EA578A7F318A /* Info.plist */, + D4DA544B2520BFA65D6DB4BB /* target.yml */, + 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */, + ); + path = SupportingFiles; + sourceTree = ""; + }; + 789DD6B31BA8BB4B3A40EF7C /* ElementX */ = { + isa = PBXGroup; + children = ( + CA90BD288E5AE6BC643AFDDF /* TemplateScreenCoordinator.swift */, + BA40B98B098B6F0371B750B3 /* TemplateScreenModels.swift */, + B43456E73F8A2D52B69B9FB9 /* TemplateScreenViewModel.swift */, + 342BEBC3C5FC3F9943C41C4C /* TemplateScreenViewModelProtocol.swift */, + 4AC3BA2B379A928301E21004 /* View */, + ); + path = ElementX; + sourceTree = ""; + }; + 79023E5904B155E8E2B8B502 /* View */ = { + isa = PBXGroup; + children = ( + 422724361B6555364C43281E /* RoomHeaderView.swift */, + 5221DFDF809142A2D6AC82B9 /* RoomScreen.swift */, + 4552D3466B1453F287223ADA /* SwipeRightAction.swift */, + 464C6BFAA853DC755B9C1F60 /* PinnedItemsBanner */, + ); + path = View; + sourceTree = ""; + }; + 79E560F5113ED25D172E550C /* Media */ = { + isa = PBXGroup; + children = ( + 669F35C505ACE1110589F875 /* MediaUploadingPreprocessor.swift */, + CA15BB3F6C62B35AE2C281A9 /* Provider */, + ); + path = Media; + sourceTree = ""; + }; + 7AE042B6E4318E352DD3991A /* View */ = { + isa = PBXGroup; + children = ( + 88410BD213FDF9B28E8B671F /* UserDetailsEditScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 7B890CCD20B037760BFDF957 /* RoomRolesAndPermissionsScreen */ = { + isa = PBXGroup; + children = ( + 7C28B70BEFD3676F11D5D51F /* RoomRolesAndPermissionsScreenCoordinator.swift */, + 1DE7969EBCAF078813E18EA1 /* RoomRolesAndPermissionsScreenModels.swift */, + 7C1AF829F12FDC99717082D9 /* RoomRolesAndPermissionsScreenViewModel.swift */, + 90DFF217B3D9D0941283278C /* RoomRolesAndPermissionsScreenViewModelProtocol.swift */, + 81D5D206BCA482C324144FBA /* View */, + ); + path = RoomRolesAndPermissionsScreen; + sourceTree = ""; + }; + 7B91CB64534AD870924CCFEF /* NotificationSettingsScreen */ = { + isa = PBXGroup; + children = ( + 2389732B0E115A999A069083 /* NotificationSettingsScreenCoordinator.swift */, + 0F64447FF544298A6A3BEF85 /* NotificationSettingsScreenModels.swift */, + 46D560DDA3B20C82766ACFAD /* NotificationSettingsScreenViewModel.swift */, + 421FA93BCC2840E66E4F306F /* NotificationSettingsScreenViewModelProtocol.swift */, + BE7641A284D3E81DC96943E3 /* View */, + ); + path = NotificationSettingsScreen; + sourceTree = ""; + }; + 7DA2A18CFD03E0BACE6B5C4B /* AnalyticsPromptScreen */ = { + isa = PBXGroup; + children = ( + 9B67DF223EEB8DCAF178A1D4 /* AnalyticsPromptScreenCoordinator.swift */, + 18486B87745B1811E7FBD3D2 /* AnalyticsPromptScreenModels.swift */, + 6C8EC6EA7EDFCE46710DA306 /* AnalyticsPromptScreenViewModel.swift */, + 7AFD012C3A9F5EF276DDD4AA /* AnalyticsPromptScreenViewModelProtocol.swift */, + 4044C040B64B9F077298C947 /* View */, + ); + path = AnalyticsPromptScreen; + sourceTree = ""; + }; + 7DBC911559934065993A5FF4 /* NotificationManager */ = { + isa = PBXGroup; + children = ( + 0376C429FAB1687C3D905F3E /* MockCoder.swift */, + 30ED584467DB380E3CEFB1DB /* NotificationManagerTests.swift */, + DC0AEA686E425F86F6BA0404 /* UNNotification+Creator.swift */, + 130ED565A078F7E0B59D9D25 /* UNTextInputNotificationResponse+Creator.swift */, + ); + path = NotificationManager; + sourceTree = ""; + }; + 7F6468993CB943953DC355A6 /* Replies */ = { + isa = PBXGroup; + children = ( + 1C25B6EBEB414431187D73B7 /* TimelineReplyView.swift */, + ); + path = Replies; + sourceTree = ""; + }; + 8039515BAA53B7C3275AC64A /* Client */ = { + isa = PBXGroup; + children = ( + 0724EBDFE8BB4C9E5547C57D /* Client.swift */, + D09A267106B9585D3D0CFC0D /* ClientError.swift */, + 18F2958E6D247AE2516BEEE8 /* ClientProxy.swift */, + 6033779EB37259F27F938937 /* ClientProxyProtocol.swift */, + 79FAC366FF299BCC555D756E /* ElementWellKnown.swift */, + ); + path = Client; + sourceTree = ""; + }; + 8081F6F9AE11BB314A838EC9 /* View */ = { + isa = PBXGroup; + children = ( + FBB0328F2887BF0A65BC5D49 /* NotificationSettingsEditScreen.swift */, + C97F8963B14EB0AF3940DDBF /* NotificationSettingsEditScreenRoomCell.swift */, + ); + path = View; + sourceTree = ""; + }; + 815092CE45A84D67A6CC7EA1 /* NetworkMonitor */ = { + isa = PBXGroup; + children = ( + 1D67E616BCA82D8A1258D488 /* NetworkMonitor.swift */, + 1575947B7A6FE08C57FE5EE4 /* NetworkMonitorProtocol.swift */, + ); + path = NetworkMonitor; + sourceTree = ""; + }; + 81D5D206BCA482C324144FBA /* View */ = { + isa = PBXGroup; + children = ( + B2B1DC3B3FB40A7F4AE9B7BF /* RoomRolesAndPermissionsScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 823ED0EC3F1B6CF47D284011 /* Tools */ = { + isa = PBXGroup; + children = ( + 52AA75722911233E40A3B366 /* Scripts */, + ); + path = Tools; + sourceTree = ""; + }; + 829DDE5AE36ADD18677C150C /* View */ = { + isa = PBXGroup; + children = ( + 97287090CA64DAA95386ECED /* ResolveVerifiedUserSendFailureScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 82D5AD3EAE3A5C1068A44A88 /* Session */ = { + isa = PBXGroup; + children = ( + 6E5E9C044BEB7C70B1378E91 /* UserSession.swift */, + 5F4134FEFE4EB55759017408 /* UserSessionProtocol.swift */, + ); + path = Session; + sourceTree = ""; + }; + 832EB453B3A5D04C18D86117 /* View */ = { + isa = PBXGroup; + children = ( + 23EE69982BBA18C6D51AD08E /* UserProfileScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 832FC81F760220239E285294 /* Proxy */ = { + isa = PBXGroup; + children = ( + 25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */, + 1B927CF5EF7FCCDA5EDC474B /* NotificationItemProxyProtocol.swift */, + ); + path = Proxy; + sourceTree = ""; + }; + 8428BD1821586CEE0B9C9ECA /* Messages */ = { + isa = PBXGroup; + children = ( + 57EAAF82432B0B53881CF826 /* AudioRoomTimelineItem.swift */, + 7475C5AE20BA896930907EA8 /* AudioRoomTimelineItemContent.swift */, + 450E04B2A976CC4C8CC1807C /* EmoteRoomTimelineItem.swift */, + EE378083653EF0C9B5E9D580 /* EmoteRoomTimelineItemContent.swift */, + 5098DA7799946A61E34A2373 /* FileRoomTimelineItem.swift */, + 216F0DDC98F2A2C162D09C28 /* FileRoomTimelineItemContent.swift */, + 3DFE4453AB0B34C203447162 /* ImageRoomTimelineItem.swift */, + B2B5EDCD05D50BA9B815C66C /* ImageRoomTimelineItemContent.swift */, + 1B2AC540DE619B36832A5DB5 /* LocationRoomTimelineItem.swift */, + CD6613DE16AD26B3A74DA1F5 /* LocationRoomTimelineItemContent.swift */, + 421E716C521F96D24ECE69B3 /* NoticeRoomTimelineItem.swift */, + 1FD51B4D5173F7FC886F5360 /* NoticeRoomTimelineItemContent.swift */, + 90A55430639712CFACA34F43 /* TextRoomTimelineItem.swift */, + 28C19F54A0C4FC9AB7ABD583 /* TextRoomTimelineItemContent.swift */, + F348B5F2C12F9D4F4B4D3884 /* VideoRoomTimelineItem.swift */, + 8C8616254EE40CA8BA5E9BC2 /* VideoRoomTimelineItemContent.swift */, + D529B976F8B2AA654D923422 /* VoiceMessageRoomTimelineItem.swift */, + 3A542DF1C3BB67D829DFDC40 /* VoiceMessages */, + ); + path = Messages; + sourceTree = ""; + }; + 864330656491EBAADA4901D3 /* Sources */ = { + isa = PBXGroup; + children = ( + D7BB243B26D54EF1A0C422C0 /* NotificationContentBuilder.swift */, + 27A1AD6389A4659AF0CEAE62 /* NotificationServiceExtension.swift */, + 566F2B84465726112B830CF6 /* Other */, + ); + path = Sources; + sourceTree = ""; + }; + 8656AFF06650360A5D0695FF /* EncryptionReset */ = { + isa = PBXGroup; + children = ( + 934A2E4A36A7FB6E301758EB /* EncryptionResetPasswordScreen */, + A3CF1DEFB89992E0B9187004 /* EncryptionResetScreen */, + ); + path = EncryptionReset; + sourceTree = ""; + }; + 87E2774157D9C4894BCFF3F8 /* MediaPickerScreen */ = { + isa = PBXGroup; + children = ( + B8A3B7637DDBD6AA97AC2545 /* CameraPicker.swift */, + 0F5567A7EF6F2AB9473236F6 /* DocumentPicker.swift */, + 64F49FB9EE2913234F06CE68 /* MediaPickerScreenCoordinator.swift */, + A232D9156D225BD9FD1D0C43 /* PhotoLibraryPicker.swift */, + ); + path = MediaPickerScreen; + sourceTree = ""; + }; + 8A4738BBA7C7A299BAD70372 /* GlobalSearchScreen */ = { + isa = PBXGroup; + children = ( + 74653BE903970C0E36867D46 /* GlobalSearchScreenCoordinator.swift */, + 436A0D98D372B17EAE9AA999 /* GlobalSearchScreenModels.swift */, + 38354164AF59C5006CD05878 /* GlobalSearchScreenViewModel.swift */, + B788615712FED326F73D3F83 /* GlobalSearchScreenViewModelProtocol.swift */, + 390C92506AD893EC593D405D /* View */, + ); + path = GlobalSearchScreen; + sourceTree = ""; + }; + 8A9C09B6A392465E03B8D1B1 /* IntegrationTests */ = { + isa = PBXGroup; + children = ( + 4EC4EBBC4F6885775F198875 /* Sources */, + 6765932445C053E15E63C29A /* SupportingFiles */, + ); + path = IntegrationTests; + sourceTree = ""; + }; + 8ACEC7D7B74641FF4DB6A6D3 /* View */ = { + isa = PBXGroup; + children = ( + 989FC684408B31A677F5538B /* CompletionSuggestionView.swift */, + 85666E40F7E817809B4FD787 /* ComposerToolbar.swift */, + FE1E6FAA3719E9B7A2D5510B /* FormattingToolbar.swift */, + 4100DDE6BF3C566AB66B80CC /* MentionSuggestionItemView.swift */, + 9F1DF3FFFE5ED2B8133F43A7 /* MessageComposer.swift */, + 345172AD4377E83A44BD864F /* MessageComposerTextField.swift */, + 128501375217576AF0FE3E92 /* RoomAttachmentPicker.swift */, + 2AE807361805463F5AEDD1CA /* VoiceMessagePreviewComposer.swift */, + 46A2AD86F7E618F468F6FAF5 /* VoiceMessageRecordingButton.swift */, + 73A5C3F7C9C1DA10CAEC6A98 /* VoiceMessageRecordingComposer.swift */, + 5E9CBF577B9711CFBB4FA40D /* VoiceMessageRecordingView.swift */, + ); + path = View; + sourceTree = ""; + }; + 8AEA6A91159FA0D3EAFCCB0D /* Sounds */ = { + isa = PBXGroup; + children = ( + ED482057AE39D5C6D9C5F3D8 /* message.caf */, + ); + path = Sounds; + sourceTree = ""; + }; + 8B5E91450E85A9689931B221 /* ComposerDraft */ = { + isa = PBXGroup; + children = ( + 1D70253004A5AEC9C73D6A4F /* ComposerDraftService.swift */, + A7E37072597F67C4DD8CC2DB /* ComposerDraftServiceProtocol.swift */, + ); + path = ComposerDraft; + sourceTree = ""; + }; + 8C3BAE06B336D97DABBE2509 /* CreateRoom */ = { + isa = PBXGroup; + children = ( + 935C2FB18EFB8EEE96B26330 /* CreateRoomFlowParameters.swift */, + ); + path = CreateRoom; + sourceTree = ""; + }; + 8F074E22FD93E64211971845 /* Onboarding */ = { + isa = PBXGroup; + children = ( + 7DA2A18CFD03E0BACE6B5C4B /* AnalyticsPromptScreen */, + 336A13CA8A1DD526D9C41DD4 /* IdentityConfirmationScreen */, + F6D661C666128C74BF0A7482 /* IdentityConfirmedScreen */, + F526F4FE387B32380592BA53 /* NotificationPermissionsScreen */, + C1CD278862878F9545608040 /* SessionVerificationScreen */, + ); + path = Onboarding; + sourceTree = ""; + }; + 8F9A844EB44B6AD7CA18FD96 /* HTMLParsing */ = { + isa = PBXGroup; + children = ( + 2A5C6FBF97B6EED3D4FA5EFF /* AttributedStringBuilder.swift */, + 72F37B5DA798C9AE436F2C2C /* AttributedStringBuilderProtocol.swift */, + 1E508AB0EDEE017FF4F6F8D1 /* DTHTMLElement+AttributedStringBuilder.swift */, + C024C151639C4E1B91FCC68B /* ElementXAttributeScope.swift */, + A436057DBEA1A23CA8CB1FD7 /* UIFont+AttributedStringBuilder.h */, + E8CA187FE656EE5A3F6C7DE5 /* UIFont+AttributedStringBuilder.m */, + ); + path = HTMLParsing; + sourceTree = ""; + }; + 90DC2E28718955ED87AD1456 /* CreatePollScreen */ = { + isa = PBXGroup; + children = ( + 25F8664F1FB95AF3C4202478 /* PollFormScreenCoordinator.swift */, + EB63761D9F9CE8B23CBD6179 /* PollFormScreenModels.swift */, + F64A8582F65567AC38C2976A /* PollFormScreenViewModel.swift */, + A40F1985065500F0E7F61A27 /* PollFormScreenViewModelProtocol.swift */, + D57A6F3FC292425BEBDF58BF /* View */, + ); + path = CreatePollScreen; + sourceTree = ""; + }; + 90F48FEF84016ED42A94BA24 /* LoginScreen */ = { + isa = PBXGroup; + children = ( + 9349F590E35CE514A71E6764 /* LoginHomeserver.swift */, + 4B41FABA2B0AEF4389986495 /* LoginMode.swift */, + 05F598B1B346DAF223651C91 /* LoginScreenCoordinator.swift */, + 0D0B159AFFBBD8ECFD0E37FA /* LoginScreenModels.swift */, + 3C368CAB3063EF275357ECD4 /* LoginScreenViewModel.swift */, + 9780389F8A53E4D26E23DD03 /* LoginScreenViewModelProtocol.swift */, + 605F8221E52991786397FCC9 /* View */, + ); + path = LoginScreen; + sourceTree = ""; + }; + 92E99C57D7F92ED16F73282C /* ElementCall */ = { + isa = PBXGroup; + children = ( + CC437C491EA6996513B1CEAB /* ElementCallConfiguration.swift */, + 33AE897D86784CCA5E4E9227 /* ElementCallService.swift */, + 406C90AF8C3E98DF5D4E5430 /* ElementCallServiceConstants.swift */, + 6FC8B21E86B137BE4E91F82A /* ElementCallServiceProtocol.swift */, + 309AD8BAE6437C31BA7157BF /* ElementCallWidgetDriver.swift */, + A6C11AD9813045E44F950410 /* ElementCallWidgetDriverProtocol.swift */, + 28C202C1C7E330F124981A31 /* GenericCallLinkWidgetDriver.swift */, + ); + path = ElementCall; + sourceTree = ""; + }; + 934A2E4A36A7FB6E301758EB /* EncryptionResetPasswordScreen */ = { + isa = PBXGroup; + children = ( + E6935A55AB3B0C94BC566DD6 /* EncryptionResetPasswordScreenCoordinator.swift */, + 54A5E6F398C269AD52C9AE21 /* EncryptionResetPasswordScreenModels.swift */, + 303D9438EFB481F57A366E82 /* EncryptionResetPasswordScreenViewModel.swift */, + 4A2B5274C1D3D2999D643786 /* EncryptionResetPasswordScreenViewModelProtocol.swift */, + 459B661EA3598F9E709E81A7 /* View */, + ); + path = EncryptionResetPasswordScreen; + sourceTree = ""; + }; + 93C7520ED23C9598BB144DBB /* UserProfileScreen */ = { + isa = PBXGroup; + children = ( + D5B4932E4EFBC8FAC10972CD /* UserProfileScreenCoordinator.swift */, + 604A69C081B935D6A38DE6D8 /* UserProfileScreenModels.swift */, + 0BD116096CAA9139B95EEA9C /* UserProfileScreenViewModel.swift */, + F134D2D91DFF732FB75B2CB7 /* UserProfileScreenViewModelProtocol.swift */, + 832EB453B3A5D04C18D86117 /* View */, + ); + path = UserProfileScreen; + sourceTree = ""; + }; + 948DD12A5533BE1BC260E437 /* LocationSharing */ = { + isa = PBXGroup; + children = ( + 8BEBF0E59F25E842EDB6FD11 /* LocationSharingScreenModels.swift */, + C15E0017717EAE3A1D02D005 /* StaticLocationScreenCoordinator.swift */, + F5311C989EC15B4C2D699025 /* StaticLocationScreenViewModel.swift */, + C616D90B1E2F033CAA325439 /* StaticLocationScreenViewModelProtocol.swift */, + 9FD8D798D879069243A7E7F7 /* View */, + ); + path = LocationSharing; + sourceTree = ""; + }; + 949B06577E5265373013DDAB /* View */ = { + isa = PBXGroup; + children = ( + FC853F9B4FBE039D2C16EC6B /* RoomMembersListManageMemberSheet.swift */, + 1B8E176484A89BAC389D4076 /* RoomMembersListScreen.swift */, + CC03209FDE8CE0810617BFFF /* RoomMembersListScreenMemberCell.swift */, + ); + path = View; + sourceTree = ""; + }; + 951A66D15CD44C0EACE4A951 /* Sources */ = { + isa = PBXGroup; + children = ( + 7D0CBC76C80E04345E11F2DB /* Application.swift */, + E8A1BBEF7318CA6B6ACCF4AE /* AppLockSetupUITests.swift */, + F733F135E6D67BBBEB76CC30 /* AppLockUITests.swift */, + 295E28C3B9EAADF519BF2F44 /* AuthenticationFlowCoordinatorUITests.swift */, + C6FEA87EA3752203065ECE27 /* BugReportUITests.swift */, + F8CEB4634C0DD7779C4AB504 /* CreateRoomScreenUITests.swift */, + 1DB34B0C74CD242FED9DD069 /* LoginScreenUITests.swift */, + 3368395F06AA180138E185B6 /* PollFormScreenUITests.swift */, + C5B7A755E985FA14469E86B2 /* RoomMembersListScreenUITests.swift */, + 45571C2EBD98ED7E0CEA7AF7 /* RoomRolesAndPermissionsUITests.swift */, + 086B997409328F091EBA43CE /* RoomScreenUITests.swift */, + 054F469E433864CC6FE6EE8E /* ServerSelectionUITests.swift */, + 6D4777F0142E330A75C46FE4 /* SessionVerificationUITests.swift */, + DA2AEC1AB349A341FE13DEC1 /* StartChatScreenUITests.swift */, + F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */, + ); + path = Sources; + sourceTree = ""; + }; + 95BE1C7CB2C80344FF0BE724 /* TimelineItems */ = { + isa = PBXGroup; + children = ( + 184CF8C196BE143AE226628D /* DecorationTimelineItemProtocol.swift */, + C0900BBF0A5D5D775E917C70 /* EventBasedMessageTimelineItemProtocol.swift */, + 218AB05B4E3889731959C5F1 /* EventBasedTimelineItemProtocol.swift */, + 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */, + 105B2A8426404EF66F00CFDB /* RoomTimelineItemFactory.swift */, + 7D25A35764C7B3DB78954AB5 /* RoomTimelineItemFactoryProtocol.swift */, + ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */, + 90F2F8998E5632668B0AD848 /* RoomTimelineItemView.swift */, + D0C2D52E36AD614B3C003EF6 /* RoomTimelineItemViewState.swift */, + 5E33FD32BBC44D703C7AE4F9 /* TextBasedRoomTimelineItem.swift */, + 75D1D02F7F3AC1122FCFB4F3 /* Items */, + ); + path = TimelineItems; + sourceTree = ""; + }; + 96111C0A11B801B19C42DCBE /* View */ = { + isa = PBXGroup; + children = ( + AD558A898847C179E4B7A237 /* SecureBackupKeyBackupScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 9613851C68D8C01EABFB3569 /* AppLock */ = { + isa = PBXGroup; + children = ( + AC0275CEE9CA078B34028BDF /* AppLockScreenViewModelTests.swift */, + DD97F9661ABF08CE002054A2 /* AppLockServiceTests.swift */, + B0BA67B3E4EF9D29D14A78CE /* AppLockSettingsScreenViewModelTests.swift */, + 52F5EE5DE3B55D59299DB5BC /* AppLockSetupBiometricsScreenViewModelTests.swift */, + 989D7380D9C86B3A10D30B13 /* AppLockSetupPINScreenViewModelTests.swift */, + 4A5B4CD611DE7E94F5BA87B2 /* AppLockTimerTests.swift */, + EF13BFD415CA84B1272E94F8 /* PINTextFieldTests.swift */, + ); + path = AppLock; + sourceTree = ""; + }; + 99B9B46F2D621380428E68F7 /* ElementX */ = { + isa = PBXGroup; + children = ( + E68740F873AB18A5C26844EA /* Sources */, + 2774D635E78D8B98390EA694 /* Resources */, + 0B7746360C4753B5A014838F /* SupportingFiles */, + ); + path = ElementX; + sourceTree = ""; + }; + 9A5AE840145B5AB195A3B186 /* Templates */ = { + isa = PBXGroup; + children = ( + 490F49F5627FBEF3BB8665A3 /* SimpleScreenExample */, + ); + path = Templates; + sourceTree = ""; + }; + 9C0C1CB9E16302C00AB4956D /* View */ = { + isa = PBXGroup; + children = ( + 46D0BA44B1838E65B507B277 /* NotificationPermissionsScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + 9C4193C4524B35FD6B94B5A9 /* Pills */ = { + isa = PBXGroup; + children = ( + 15748C254911E3654C93B0ED /* MentionBuilder.swift */, + E1E0B4A34E69BD2132BEC521 /* MessageText.swift */, + 1B53D6C5C0D14B04D3AB3F6E /* PillAttachmentViewProvider.swift */, + CB8D34E94AB07128DB73D6C7 /* PillConstants.swift */, + 86376BEE425704AEE197CA54 /* PillContext.swift */, + 9CF1EE0AA78470C674554262 /* PillTextAttachment.swift */, + 913C8E13B8B602C7B6C0C4AE /* PillTextAttachmentData.swift */, + 7773CBFDBD458E0B7E270507 /* PillView.swift */, + 8AE78FA0011E07920AE83135 /* PlainMentionBuilder.swift */, + ); + path = Pills; + sourceTree = ""; + }; + 9F7C2D63C42828D8931D5286 /* CollapsibleFlowLayout */ = { + isa = PBXGroup; + children = ( + 1F7C6DDBB5D12F6EF6A3D6E1 /* CollapsibleReactionLayout.swift */, + ); + path = CollapsibleFlowLayout; + sourceTree = ""; + }; + 9FD8D798D879069243A7E7F7 /* View */ = { + isa = PBXGroup; + children = ( + 9B06663F7858E45882E63471 /* StaticLocationScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + A040ACE4D778FFCD65DDF5F8 /* ResolveVerifiedUserSendFailureScreen */ = { + isa = PBXGroup; + children = ( + C5AEB5907E24092D741718AF /* ResolveVerifiedUserSendFailureScreenCoordinator.swift */, + 60011EF0086E49DBD78E16E5 /* ResolveVerifiedUserSendFailureScreenModels.swift */, + 574CB70E82D7EAEA538E4135 /* ResolveVerifiedUserSendFailureScreenViewModel.swift */, + 56852036214ABA9D7D305768 /* ResolveVerifiedUserSendFailureScreenViewModelProtocol.swift */, + 829DDE5AE36ADD18677C150C /* View */, + ); + path = ResolveVerifiedUserSendFailureScreen; + sourceTree = ""; + }; + A0C06C0F6A8621B22BFAEB56 /* Localizations */ = { + isa = PBXGroup; + children = ( + 91DE43B8815918E590912DDA /* InfoPlist.strings */, + 7109E709A7738E6BCC4553E6 /* Localizable.strings */, + 187853A7E643995EE49FAD43 /* Localizable.stringsdict */, + 135FC689EA39AE1D34153B58 /* SAS.strings */, + D2F7194F440375338F8E2487 /* Untranslated.strings */, + F75DF9500D69A3AAF8339E69 /* Untranslated.stringsdict */, + ); + path = Localizations; + sourceTree = ""; + }; + A0D745ADE5568E50270F70EF /* SupportingFiles */ = { + isa = PBXGroup; + children = ( + DBEDCEC9D908C19C63D24395 /* Info.plist */, + 267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */, + 90791B9C739C716A40E1B230 /* target.yml */, + ); + path = SupportingFiles; + sourceTree = ""; + }; + A151229F1A2347F37558496A /* View */ = { + isa = PBXGroup; + children = ( + BA919F521E9F0EE3638AFC85 /* BugReportScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + A33CE1B72A29E3931CBEC2A5 /* VoiceMessage */ = { + isa = PBXGroup; + children = ( + AD0FF64B0E6470F66F42E182 /* EstimatedWaveformView.swift */, + B8516302ACCA94A0E680AB3B /* VoiceMessageButton.swift */, + FB9EABCA9348DFA27439A809 /* WaveformCursorView.swift */, + BFEE91FB8ABB5F5884B6D940 /* WaveformInteractionModifier.swift */, + 94028A227645FA880B966211 /* WaveformSource.swift */, + ); + path = VoiceMessage; + sourceTree = ""; + }; + A3CF1DEFB89992E0B9187004 /* EncryptionResetScreen */ = { + isa = PBXGroup; + children = ( + E0FF9CB3EFA753277291F609 /* EncryptionResetScreenCoordinator.swift */, + 306AB507E1027D6C5C147EB6 /* EncryptionResetScreenModels.swift */, + 5875F7C0A2398E9F134B1284 /* EncryptionResetScreenViewModel.swift */, + 7E8562F4D7DE073BC32902AB /* EncryptionResetScreenViewModelProtocol.swift */, + D382E465AF067C1BF888BF8E /* View */, + ); + path = EncryptionResetScreen; + sourceTree = ""; + }; + A448A3A8F764174C60CD0CA1 /* Other */ = { + isa = PBXGroup; + children = ( + BF34A2FD6797535C95AC918D /* PlaceholderScreenCoordinator.swift */, + 854BCEAF2A832176FAACD2CB /* SplashScreenCoordinator.swift */, + ); + path = Other; + sourceTree = ""; + }; + A4852B57D55D71EEBFCD931D /* UnitTests */ = { + isa = PBXGroup; + children = ( + E600AACDF87CDBCE32683236 /* Resources */, + 73CD9796729EB702B4DFA88C /* Sources */, + 24FD174C31912A5FACFEAFB5 /* SupportingFiles */, + ); + path = UnitTests; + sourceTree = ""; + }; + A6AA0A048CAE428A5CA4CBBB /* LayoutTests */ = { + isa = PBXGroup; + children = ( + AC5F5209279A752D98AAC4B2 /* CollapsibleFlowLayoutTests.swift */, + BC8AA23D4F37CC26564F63C5 /* LayoutMocks.swift */, + ); + path = LayoutTests; + sourceTree = ""; + }; + A722D372674EE5687E1A67E4 /* View */ = { + isa = PBXGroup; + children = ( + 5FACD034DB52525A3CEF2BDF /* SessionVerificationScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + A78C2592419CA4C76FBA8FD2 /* Application */ = { + isa = PBXGroup; + children = ( + 8FC803282F9268D49F4ABF14 /* AppCoordinator.swift */, + FBC776F301D374A3298C69DA /* AppCoordinatorProtocol.swift */, + 077D7C3BE199B6E5DDEC07EC /* AppCoordinatorStateMachine.swift */, + C75EF87651B00A176AB08E97 /* AppDelegate.swift */, + CA89A2DD51B6BBE1DA55E263 /* Application.swift */, + B53AC78E49A297AC1D72A7CF /* AppMediator.swift */, + 05AF58372CA884A789EB9C5A /* AppMediatorProtocol.swift */, + AC3F82523D6F48B926D6AF68 /* AppSettings.swift */, + B251F5B4511D1CA0BA8361FE /* CoordinatorProtocol.swift */, + 7B9FCA1CFD07B8CF9BD21266 /* FlowCoordinatorProtocol.swift */, + 57F95CADD0A5DBD76B990FCB /* ServiceLocator.swift */, + 780F74C73E826685A9DB289B /* Navigation */, + 703929219780FFABAC6380AA /* Windowing */, + ); + path = Application; + sourceTree = ""; + }; + A7F3784CAF9F4CF654BC52CD /* View */ = { + isa = PBXGroup; + children = ( + 6861FE915C7B5466E6962BBA /* StartChatScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + AAFDD509929A0CCF8BCE51EB /* Authentication */ = { + isa = PBXGroup; + children = ( + 0F569CFB77E0D40BD82203D9 /* AuthenticationClientBuilder.swift */, + F3A1AB5A84D843B6AC8D5F1E /* AuthenticationService.swift */, + 5E75948AA1FE1D1A7809931F /* AuthenticationServiceProtocol.swift */, + DA38899517F08FE2AF34EB45 /* MockAuthenticationService.swift */, + A69869844D2B6F5BD9AABF85 /* OIDCConfigurationProxy.swift */, + ); + path = Authentication; + sourceTree = ""; + }; + AAFE4295DD635085A44CBF4C /* View */ = { + isa = PBXGroup; + children = ( + D39D7F513A36C9C1951DB44C /* AnalyticsSettingsScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + AC24CD8D1E51188678C6AE07 /* View */ = { + isa = PBXGroup; + children = ( + D3F275432954C8C6B1B7D966 /* AppLockSetupPINScreen.swift */, + 3D1D4A6D451F43A03CACD01D /* PINTextField.swift */, + ); + 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 */, + D5E26C54362206BBDD096D83 /* test_audio.mp3 */, + C733D11B421CFE3A657EF230 /* test_image.png */, + 3FFDA99C98BE05F43A92343B /* test_pdf.pdf */, + 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */, + ); + path = Media; + sourceTree = ""; + }; + AD5FCF9340D670C526AD17E4 /* UI */ = { + isa = PBXGroup; + children = ( + 9873076F224E4CE09D8BD47D /* TemplateScreenUITests.swift */, + ); + path = UI; + sourceTree = ""; + }; + B04B538A859CD012755DC19C /* NSE */ = { + isa = PBXGroup; + children = ( + 864330656491EBAADA4901D3 /* Sources */, + 3FDB9ADD4A6456674E748166 /* SupportingFiles */, + ); + path = NSE; + sourceTree = ""; + }; + B1FC81662045E2369B0C4A0E /* Other */ = { + isa = PBXGroup; + children = ( + E9A3D3CFA199FA7897364547 /* CallInviteRoomTimelineItem.swift */, + E1ED17433ADC77287F8904F9 /* CallNotificationRoomTimelineItem.swift */, + A7C4EA55DA62F9D0F984A2AE /* CollapsibleTimelineItem.swift */, + 5351EBD7A0B9610548E4B7B2 /* EncryptedRoomTimelineItem.swift */, + 5281C5CDC4A712265A0B5FBF /* PollRoomTimelineItem.swift */, + E6E6BDF9D26DB05C88901416 /* RedactedRoomTimelineItem.swift */, + B16048D30F0438731C41F775 /* StateRoomTimelineItem.swift */, + 818695BED971753243FEF897 /* StickerRoomTimelineItem.swift */, + F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */, + ); + path = Other; + sourceTree = ""; + }; + B1FD4FD6CEB987AE274AEEE5 /* SecureBackupKeyBackupScreen */ = { + isa = PBXGroup; + children = ( + 4B2D4EEBE8C098BBADD10939 /* SecureBackupKeyBackupScreenCoordinator.swift */, + AD72A9B720D75DBE60AC299F /* SecureBackupKeyBackupScreenModels.swift */, + 82B612853BFB68373249777B /* SecureBackupKeyBackupScreenViewModel.swift */, + 4525E8C0FBDD27D1ACE90952 /* SecureBackupKeyBackupScreenViewModelProtocol.swift */, + 96111C0A11B801B19C42DCBE /* View */, + ); + path = SecureBackupKeyBackupScreen; + sourceTree = ""; + }; + B23135B06B044CB811139D2F /* Generated */ = { + isa = PBXGroup; + children = ( + 57916A1578D8043BB0795441 /* GeneratedMocks.swift */, + C2F079B5DBD0D85FEA687AAE /* SDKGeneratedMocks.swift */, + ); + path = Generated; + sourceTree = ""; + }; + B364E08924AD15820350CDD9 /* SettingsScreen */ = { + isa = PBXGroup; + children = ( + 5B8F0ED874DF8C9A51B0AB6F /* SettingsScreenCoordinator.swift */, + 9B663BE498BB39EADC24025D /* SettingsScreenModels.swift */, + 4E625B0EB2F86B37C14EF7E6 /* SettingsScreenViewModel.swift */, + 2AF715D4FD4710EBB637D661 /* SettingsScreenViewModelProtocol.swift */, + 26C16326BCCCED74A85A0F48 /* View */, + ); + path = SettingsScreen; + sourceTree = ""; + }; + B470504BE2DC95FAC94FDD79 /* ReadReceipts */ = { + isa = PBXGroup; + children = ( + 3D75941CBD7D336F831924EC /* ReadReceiptCell.swift */, + 8063E65441E771200108C558 /* ReadReceiptsSummaryView.swift */, + ); + path = ReadReceipts; + sourceTree = ""; + }; + B53CA9BECD3F97805E1432D0 /* HomeScreen */ = { + isa = PBXGroup; + children = ( + D653265D006E708E4E51AD64 /* HomeScreenCoordinator.swift */, + 71BC7CA1BC1041E93077BBA1 /* HomeScreenModels.swift */, + 31D6764D6976D235926FE5FC /* HomeScreenViewModel.swift */, + 24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */, + 4F43EBE458FBE634996AD7C6 /* View */, + ); + path = HomeScreen; + sourceTree = ""; + }; + B687E3E8C23415A06A3D5C65 /* UserIndicator */ = { + isa = PBXGroup; + children = ( + E8AE4B3273BA189FDCD4055C /* UserIndicator.swift */, + FD1275D9CE0FFBA6E8E85426 /* UserIndicatorController.swift */, + A12D3B1BCF920880CA8BBB6B /* UserIndicatorControllerProtocol.swift */, + E43005941B3A2C9671E23C85 /* UserIndicatorModalView.swift */, + 6AB54B4F94686CCF0289B72F /* UserIndicatorPresenter.swift */, + F57C8022B8A871A1DCD1750A /* UserIndicatorToastView.swift */, + ); + path = UserIndicator; + sourceTree = ""; + }; + B86CF59E083C82C2A842E4AD /* RoomMemberDetailsScreen */ = { + isa = PBXGroup; + children = ( + 0FA60F848D1C14F873F9621A /* RoomMemberDetailsScreenCoordinator.swift */, + 1B6E30BB748F3F480F077969 /* RoomMemberDetailsScreenModels.swift */, + 84A87D0471D438A233C2CF4A /* RoomMemberDetailsScreenViewModel.swift */, + 7DDF49CEBC0DFC59C308335F /* RoomMemberDetailsScreenViewModelProtocol.swift */, + 3564D09CBD6B24EA35A760B0 /* View */, + ); + path = RoomMemberDetailsScreen; + sourceTree = ""; + }; + B8DF5C80CDA495A1E5ED20D9 /* View */ = { + isa = PBXGroup; + children = ( + C18CC37B97E77838609CFFE7 /* AdvancedSettingsScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + BA1938A75D8C780F694CEB62 /* ServerConfirmationScreen */ = { + isa = PBXGroup; + children = ( + 03277E40D0E0DE0712021A71 /* ServerConfirmationScreenCoordinator.swift */, + 9342F5D6729627B6393AF853 /* ServerConfirmationScreenModels.swift */, + 24DEE0682C95F897B6C7CB0D /* ServerConfirmationScreenViewModel.swift */, + ABA4CF2F5B4F68D02E412004 /* ServerConfirmationScreenViewModelProtocol.swift */, + 2CAAA563083EAC0FA6BDC4F3 /* View */, + ); + path = ServerConfirmationScreen; + sourceTree = ""; + }; + BDCEF7C3BF6D09F5611CFC8B /* SecureBackup */ = { + isa = PBXGroup; + children = ( + 5A1119E9C63AE530252640D2 /* SecureBackupController.swift */, + 1C21A715237F2B6D6E80998C /* SecureBackupControllerProtocol.swift */, + ); + path = SecureBackup; + sourceTree = ""; + }; + BE7641A284D3E81DC96943E3 /* View */ = { + isa = PBXGroup; + children = ( + C5F06F2F09B2EDD067DC2174 /* NotificationSettingsScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + C0937E3B06A8F0E2DB7C8241 /* Other */ = { + isa = PBXGroup; + children = ( + 04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */, + 3D65BCC659FD9087E49B3C25 /* AppAppearance.swift */, + E24B88AD3D1599E8CB1376E0 /* AvatarSize.swift */, + E5272BC4A60B6AD7553BACA1 /* BlurHashDecode.swift */, + 9332DFE9642F0A46ECA0497B /* BlurHashEncode.swift */, + AE52983FAFB4E0998C00EE8A /* CancellableTask.swift */, + 127A57D053CE8C87B5EFB089 /* Consumable.swift */, + 127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */, + 5D99730313BEBF08CDE81EE3 /* EmojiDetection.swift */, + 7B25F959A434BB9923A3223F /* ExpiringTaskRunner.swift */, + 6A580295A56B55A856CC4084 /* InfoPlistReader.swift */, + 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */, + B3A1398EFF65090FDA1CB639 /* ProcessInfo.swift */, + 53482ECA4B6633961EC224F5 /* ScrollViewAdapter.swift */, + 4481799F455B3DA243BDA2AC /* ShareToMapsAppActivity.swift */, + B1E227F34BE43B08E098796E /* TestablePreview.swift */, + 1F2529D434C750ED78ADF1ED /* UserAgentBuilder.swift */, + 35FA991289149D31F4286747 /* UserPreference.swift */, + 7431C962E314ADAE38B6D708 /* Analytics */, + 9F7C2D63C42828D8931D5286 /* CollapsibleFlowLayout */, + 349FE0C25B41C7AC9B7C623F /* EffectsScene */, + 44BBB96FAA2F0D53C507396B /* Extensions */, + 8F9A844EB44B6AD7CA18FD96 /* HTMLParsing */, + 06501F0E978B2D5C92771DC7 /* Logging */, + C17C3586C93F3A314C1CC318 /* MapLibre */, + 815092CE45A84D67A6CC7EA1 /* NetworkMonitor */, + 9C4193C4524B35FD6B94B5A9 /* Pills */, + 25852CD5316875417111E5CA /* Progress */, + 052CC920F473C10B509F9FC1 /* SwiftUI */, + B687E3E8C23415A06A3D5C65 /* UserIndicator */, + A33CE1B72A29E3931CBEC2A5 /* VoiceMessage */, + ); + path = Other; + sourceTree = ""; + }; + C0FAC17D4DD7D3A502822550 /* UITests */ = { + isa = PBXGroup; + children = ( + 951A66D15CD44C0EACE4A951 /* Sources */, + 78915D878159D302395D57BF /* SupportingFiles */, + ); + path = UITests; + sourceTree = ""; + }; + C13DBC8C4A879A5A9C781BBD /* Polls */ = { + isa = PBXGroup; + children = ( + A6B19D10B102956066AF117B /* PollOptionView.swift */, + 638790D3F915F0909315C47A /* PollView.swift */, + ); + path = Polls; + sourceTree = ""; + }; + C17C3586C93F3A314C1CC318 /* MapLibre */ = { + isa = PBXGroup; + children = ( + AAD8234D0E9C9B12BF9F240B /* LocationAnnotation.swift */, + B48B7AD4908C5C374517B892 /* MapAssets.xcassets */, + 622D09D4ECE759189009AEAF /* MapLibreMapView.swift */, + B81B6170DB690013CEB646F4 /* MapLibreModels.swift */, + 592A35163B0749C66BFD6186 /* MapLibreStaticMapView.swift */, + E062C1750EFC8627DE4CAB8E /* MapTilerAuthorization.swift */, + 1A4D29F2683F5772AC72406F /* MapTilerStaticMap.swift */, + 20872C3887F835958CE2F1D0 /* MapTilerStaticMapProtocol.swift */, + F0B9F5BC4C80543DE7228B9D /* MapTilerStyle.swift */, + B7AE92E7BFF71797BDE1D261 /* MapTilerStyleBuilder.swift */, + 225EFCA26877E75CDFE7F48D /* MapTilerStyleBuilderProtocol.swift */, + ); + path = MapLibre; + sourceTree = ""; + }; + C18958141C8ED6D778F779A4 /* CreateRoom */ = { + isa = PBXGroup; + children = ( + C618CA2B6C8758B06C88013C /* CreateRoomCoordinator.swift */, + 7B849D2FF2CC12BA411A1651 /* CreateRoomModels.swift */, + 15A657D96779D1DEB8EF1327 /* CreateRoomViewModel.swift */, + 340179A0FC1AD4AEDA7FC134 /* CreateRoomViewModelProtocol.swift */, + F84100ED0C09031BAB7BB77E /* View */, + ); + path = CreateRoom; + sourceTree = ""; + }; + C1CD278862878F9545608040 /* SessionVerificationScreen */ = { + isa = PBXGroup; + children = ( + 796CBD0C56FA0D3AEDAB255B /* SessionVerificationScreenCoordinator.swift */, + AF848B41DAF1066F3054D4A1 /* SessionVerificationScreenModels.swift */, + 161CD412E75F4086F422AE39 /* SessionVerificationScreenStateMachine.swift */, + ED33988DA4FD4FC666800106 /* SessionVerificationScreenViewModel.swift */, + A7D452AF7B5F7E3A0A7DB54C /* SessionVerificationScreenViewModelProtocol.swift */, + A722D372674EE5687E1A67E4 /* View */, + ); + path = SessionVerificationScreen; + sourceTree = ""; + }; + C45CF12DD74BF5B6C970C5E1 /* RoomDirectorySearchScreen */ = { + isa = PBXGroup; + children = ( + 1562EAF6231151A675BED7A9 /* RoomDirectorySearchScreenCoordinator.swift */, + 41BB37D96C3EA18F3CE8675D /* RoomDirectorySearchScreenModels.swift */, + 3984C93B8E9B10C92DADF9EE /* RoomDirectorySearchScreenScreenModelProtocol.swift */, + CCF71646898A2F720C5BFDF5 /* RoomDirectorySearchScreenViewModel.swift */, + 4BF0F0C4AA1F62828A89099E /* View */, + ); + path = RoomDirectorySearchScreen; + sourceTree = ""; + }; + C844840F3DD48A154C65AE0C /* View */ = { + isa = PBXGroup; + children = ( + BFA9EA59D5C0DA1BFC7B3621 /* QRCodeLoginScreen.swift */, + 92DB574F954CC2B40F7BE892 /* QRCodeScannerView.swift */, + ); + path = View; + sourceTree = ""; + }; + CA15BB3F6C62B35AE2C281A9 /* Provider */ = { + isa = PBXGroup; + children = ( + DEC1D382565A4E9CAC2F14EA /* MediaFileHandleProxy.swift */, + 8AFCE895ECFFA53FEE64D62B /* MediaLoader.swift */, + 1A02406480C351B8C6E0682C /* MediaLoaderProtocol.swift */, + F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */, + 85EB16E7FE59A947CA441531 /* MediaProviderProtocol.swift */, + D49B9785E3AD7D1C15A29F2F /* MediaSourceProxy.swift */, + 4FD6E621CC5E6D4830D96D2D /* MockMediaProvider.swift */, + ); + path = Provider; + sourceTree = ""; + }; + CA555F7C7CA382ACACF0D82B /* Keychain */ = { + isa = PBXGroup; + children = ( + 2355398E4A55DA5A89128AD1 /* EncryptionKeyProvider.swift */, + E78FC546F28E045A560F2963 /* EncryptionKeyProviderProtocol.swift */, + E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */, + 39C0D861FC397AC34BCF089E /* KeychainControllerMock.swift */, + E5E94DCFEE803E5ABAE8ACCE /* KeychainControllerProtocol.swift */, + ); + path = Keychain; + sourceTree = ""; + }; + CBBF6127C313A5412E438BC6 /* UserSession */ = { + isa = PBXGroup; + children = ( + 3558A15CFB934F9229301527 /* RestorationToken.swift */, + 43C2067FF58B4996323EB40C /* SessionDirectories.swift */, + 0E8BDC092D817B68CD9040C5 /* UserSessionStore.swift */, + BEBA759D1347CFFB3D84ED1F /* UserSessionStoreProtocol.swift */, + ); + path = UserSession; + sourceTree = ""; + }; + CC2B160BAFD5FEAC106F89F3 /* TimelineItemViews */ = { + isa = PBXGroup; + children = ( + B2EAFFD44F81F86012D6EC27 /* AudioRoomTimelineView.swift */, + 664ABD745A746C45CB842158 /* CallInviteRoomTimelineView.swift */, + AD6E082B0507FB28F966516A /* CallNotificationRoomTimelineView.swift */, + BFBF273BC2BFB9F3EEFA988B /* CollapsibleRoomTimelineView.swift */, + 44ABA63DBE7F76C58260B43B /* EmoteRoomTimelineView.swift */, + 2F06F70B9C433BAD4BC6B9F5 /* EncryptedRoomTimelineView.swift */, + 4F75EF13F49DD2204E760910 /* FileRoomTimelineView.swift */, + C258C9C815272911A5B132C3 /* FormattedBodyText.swift */, + 59B7CC77B82C6C67DE3AD869 /* HighlightedTimelineItemModifier.swift */, + C5599255A6C98EBDA77B76E6 /* ImageRoomTimelineView.swift */, + ED49073BB1C1FC649DAC2CCD /* LocationRoomTimelineView.swift */, + 3F54FA7C5CB7B342EF9B9B2F /* NoticeRoomTimelineView.swift */, + 4E7F7A975514E850A834B29F /* PaginationIndicatorRoomTimelineView.swift */, + AF8548D48512127CCC17C520 /* PollRoomTimelineView.swift */, + 012A284622B32052015F1F89 /* ReadMarkerRoomTimelineView.swift */, + 91C8BD78F7B9247AC57FA1A3 /* RedactedRoomTimelineView.swift */, + 2910422CB628D3B2BBE47449 /* SeparatorRoomTimelineView.swift */, + B2AF1828A5B76B7C371240FE /* StateRoomTimelineView.swift */, + D5338450E6783A576B5C16DD /* StickerRoomTimelineView.swift */, + A6EA0D8B0BBD8805F7D5A133 /* TextBasedRoomTimelineViewProtocol.swift */, + 4853C923A1AF43711D025EAF /* TextRoomTimelineView.swift */, + 44ECC9D66400727DFFEE12E8 /* TimelineStartRoomTimelineView.swift */, + C9E535B3388755B65C34CD10 /* UnsupportedRoomTimelineView.swift */, + ED0CBEAB5F796BEFBAF7BB6A /* VideoRoomTimelineView.swift */, + ); + path = TimelineItemViews; + sourceTree = ""; + }; + CE2FBFD64A89F5DBE4EB30DB /* Layout */ = { + isa = PBXGroup; + children = ( + 42236480CF0431535EBE8387 /* CustomLayoutLabelStyle.swift */, + 565F1B2B300597C616B37888 /* FullscreenDialog.swift */, + 49ABAB186CF00B15C5521D04 /* MenuSheetLabelStyle.swift */, + 398817652FA8ABAE0A31AC6D /* ReadableFrameModifier.swift */, + 5D82F234B3576BD6268C7950 /* ScaledFrameModifier.swift */, + EC5D7DA665E1F5F509C994C7 /* ScaledOffsetModifier.swift */, + E26C69EC1157D71CC61ADAE4 /* ScaledPaddingModifier.swift */, + 933B074F006F8E930DB98B4E /* TimelineMediaFrame.swift */, + EFF7BF82A950B91BC5469E91 /* ViewFrameReader.swift */, + ); + path = Layout; + sourceTree = ""; + }; + D382E465AF067C1BF888BF8E /* View */ = { + isa = PBXGroup; + children = ( + 811E8BF34E931D51552C9C13 /* EncryptionResetScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + D4B487C81A239A9C71807601 /* View */ = { + isa = PBXGroup; + children = ( + 42C8C368A611B9CB79C7F5FA /* RoomPollsHistoryScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + D4DB8163C10389C069458252 /* RoomMemberListScreen */ = { + isa = PBXGroup; + children = ( + 5AEA0B743847CFA5B3C38EE4 /* RoomMembersListScreenCoordinator.swift */, + 2D0946F77B696176E062D037 /* RoomMembersListScreenModels.swift */, + ECF79FB25E2D4BD6F50CE7C9 /* RoomMembersListScreenViewModel.swift */, + 45CDF9A107BFE6C79B58D6B5 /* RoomMembersListScreenViewModelProtocol.swift */, + 949B06577E5265373013DDAB /* View */, + ); + path = RoomMemberListScreen; + sourceTree = ""; + }; + D57A6F3FC292425BEBDF58BF /* View */ = { + isa = PBXGroup; + children = ( + D622EC7898469BB1D0881CDD /* PollFormScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + D57B3BC211BB74420C9138D7 /* RoomPollsHistoryScreen */ = { + isa = PBXGroup; + children = ( + D1D8479BB704B7EF696F8ABE /* RoomPollsHistoryScreenCoordinator.swift */, + 6E964AF2DFEB31E2B799999F /* RoomPollsHistoryScreenModels.swift */, + F0E14FF533D25A0692F7CEB0 /* RoomPollsHistoryScreenViewModel.swift */, + A130A2251A15A7AACC84FD37 /* RoomPollsHistoryScreenViewModelProtocol.swift */, + D4B487C81A239A9C71807601 /* View */, + ); + path = RoomPollsHistoryScreen; + sourceTree = ""; + }; + D8388454B5909D862CAC78F7 /* RoomChangeRolesScreen */ = { + isa = PBXGroup; + children = ( + 82DFA1B7B088D033E0794B82 /* RoomChangeRolesScreenCoordinator.swift */, + 48A5C34C4E4268EF65D171EF /* RoomChangeRolesScreenModels.swift */, + B14B1DE3E2D5D26732C49036 /* RoomChangeRolesScreenViewModel.swift */, + 7AAD8C633AA57948B34EDCF7 /* RoomChangeRolesScreenViewModelProtocol.swift */, + 5AD98DB6E142A4A4A2D8BA2D /* View */, + ); + path = RoomChangeRolesScreen; + sourceTree = ""; + }; + D847C12EC9B19A5FCDF2C815 /* WebRegistrationScreen */ = { + isa = PBXGroup; + children = ( + C7D851A10FDA55579960DC61 /* WebRegistrationScreenCoordinator.swift */, + F7C161B06F417CA5D1F1E088 /* WebRegistrationScreenModels.swift */, + A6702BC84D3CC2421D78CD4E /* WebRegistrationScreenViewModel.swift */, + 6F418426410F3823F3EB0828 /* WebRegistrationScreenViewModelProtocol.swift */, + 25A88085FB8D8227DCDB0C9C /* View */, + ); + path = WebRegistrationScreen; + sourceTree = ""; + }; + D977D4E565C06D3F41C8F8FC /* Virtual */ = { + isa = PBXGroup; + children = ( + 0B987FC3FDBAA0E1C5AA235C /* PaginationIndicatorRoomTimelineItem.swift */, + DF3D25B3EDB283B5807EADCF /* ReadMarkerRoomTimelineItem.swift */, + C6A9F49B3EE59147AF2F70BB /* SeparatorRoomTimelineItem.swift */, + D8F5F9E02B1AB5350B1815E7 /* TimelineStartRoomTimelineItem.swift */, + ); + path = Virtual; + sourceTree = ""; + }; + DAB7DC51866A6D1B51BDC3A2 /* RoomChangePermissionsScreen */ = { + isa = PBXGroup; + children = ( + 0D879FC4E881E748BB9B34DC /* RoomChangePermissionsScreenCoordinator.swift */, + C729D95CB4588D4D9AAC3DFA /* RoomChangePermissionsScreenModels.swift */, + 7AE75941583A033A9EDC9FE0 /* RoomChangePermissionsScreenViewModel.swift */, + 2721D7B051F0159AA919DA05 /* RoomChangePermissionsScreenViewModelProtocol.swift */, + 17765802D2723FB2D9A6FF89 /* View */, + ); + path = RoomChangePermissionsScreen; + sourceTree = ""; + }; + DD96B3F20F354494DECBC4F7 /* View */ = { + isa = PBXGroup; + children = ( + 70C86696AC9521F8ED88FBEB /* MediaUploadPreviewScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + DDC32FD8B94AA19C4FC062AD /* View */ = { + isa = PBXGroup; + children = ( + 00AFC5F08734C2EA4EE79C59 /* IdentityConfirmationScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + DDF77194AB6E167891D0A8F3 /* View */ = { + isa = PBXGroup; + children = ( + B746EFA112532A7B701FB914 /* RoomNotificationSettingsCustomSectionView.swift */, + 8896CDD20CA2D87EA3B848A1 /* RoomNotificationSettingsScreen.swift */, + 3203C6566DC17B7AECC1B7FD /* RoomNotificationSettingsUserDefinedScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + DF10E31B5AA21015971C3FAD /* View */ = { + isa = PBXGroup; + children = ( + 38E521D6C2BF8DF0DFB35146 /* DeveloperOptionsScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + E2DA161C142B7AB8CC40F752 /* Animation */ = { + isa = PBXGroup; + children = ( + EF1593DD87F974F8509BB619 /* ElementAnimations.swift */, + 97CE98208321C4D66E363612 /* ShimmerModifier.swift */, + ); + path = Animation; + sourceTree = ""; + }; + E4E42F93A69AE52E6FAE9412 /* Users */ = { + isa = PBXGroup; + children = ( + D071F86CD47582B9196C9D16 /* UserDiscoverySection.swift */, + 65AAD845E53B0C8B5E0812C2 /* UserDiscoveryService.swift */, + 7F615A00DB223FF3280204D2 /* UserDiscoveryServiceProtocol.swift */, + 51C454AE59914B551A6D02C0 /* UserProfileProxy.swift */, + ); + path = Users; + sourceTree = ""; + }; + E59565F441830B19DBAE567C /* Screens */ = { + isa = PBXGroup; + children = ( + 13263FFEA7749D822B51AA90 /* AppLock */, + E74CD7681375AD2EAA34D66B /* Authentication */, + 295BCC81AB45927F5F2033B1 /* AuthenticationStartScreen */, + EFD4F7FCAAAB3EF45EE7A067 /* BlockedUsersScreen */, + 53FB148CD26AFB6A5B9E20B3 /* BugReportScreen */, + 1185EECDD07495D65AC84AFC /* CallScreen */, + 90DC2E28718955ED87AD1456 /* CreatePollScreen */, + C18958141C8ED6D778F779A4 /* CreateRoom */, + 6C708A9F46EDE1105C640335 /* DeactivateAccountScreen */, + F5A65D1D3B83593598DC278D /* EmojiPickerScreen */, + 8656AFF06650360A5D0695FF /* EncryptionReset */, + 448435400B561C40E514BE1C /* FilePreviewScreen */, + 8A4738BBA7C7A299BAD70372 /* GlobalSearchScreen */, + B53CA9BECD3F97805E1432D0 /* HomeScreen */, + F12966DF3DA87FEF21348D60 /* InviteUsersScreen */, + FFD7C58CA6A7D6BBC2F584B5 /* JoinRoomScreen */, + 948DD12A5533BE1BC260E437 /* LocationSharing */, + 73E032ADD008D63812791D97 /* LogViewerScreen */, + 87E2774157D9C4894BCFF3F8 /* MediaPickerScreen */, + 23605DD08620BE6558242469 /* MediaUploadPreviewScreen */, + 3348D14DBDB54E72FC67E2F3 /* MessageForwardingScreen */, + 8F074E22FD93E64211971845 /* Onboarding */, + A448A3A8F764174C60CD0CA1 /* Other */, + 3E535010B850B53DDD3CFF2A /* PinnedEventsTimelineScreen */, + 3D733E8352DD4C461CFD8B8A /* QRCodeLoginScreen */, + 5970F275D6014548DCED6106 /* ReportContentScreen */, + A040ACE4D778FFCD65DDF5F8 /* ResolveVerifiedUserSendFailureScreen */, + DAB7DC51866A6D1B51BDC3A2 /* RoomChangePermissionsScreen */, + D8388454B5909D862CAC78F7 /* RoomChangeRolesScreen */, + E71742A824A7192C8D378875 /* RoomDetailsEditScreen */, + E703BBD16266053B8A193C7B /* RoomDetailsScreen */, + C45CF12DD74BF5B6C970C5E1 /* RoomDirectorySearchScreen */, + B86CF59E083C82C2A842E4AD /* RoomMemberDetailsScreen */, + D4DB8163C10389C069458252 /* RoomMemberListScreen */, + 0210F4932B59277E2EEEF7BC /* RoomNotificationSettingsScreen */, + D57B3BC211BB74420C9138D7 /* RoomPollsHistoryScreen */, + 7B890CCD20B037760BFDF957 /* RoomRolesAndPermissionsScreen */, + 679E9837ECA8D6776079D16E /* RoomScreen */, + 2565414373E6F68005966B8E /* SecureBackup */, + 70B74A432C241E56A7ACE610 /* Settings */, + EC4545C7E37E8294D3FE6800 /* StartChatScreen */, + 15D44FCA9475E660B7F56DB9 /* Timeline */, + 93C7520ED23C9598BB144DBB /* UserProfileScreen */, + ); + path = Screens; + sourceTree = ""; + }; + E600AACDF87CDBCE32683236 /* Resources */ = { + isa = PBXGroup; + children = ( + ACF39CFC617601C942702CDC /* Media */, + ); + path = Resources; + sourceTree = ""; + }; + E68740F873AB18A5C26844EA /* Sources */ = { + isa = PBXGroup; + children = ( + A78C2592419CA4C76FBA8FD2 /* Application */, + 0787F81684E503024BD0C051 /* Services */, + 593C7129C5927E25AD8B688F /* FlowCoordinators */, + E59565F441830B19DBAE567C /* Screens */, + C0937E3B06A8F0E2DB7C8241 /* Other */, + 2ECFF6B05DAA37EB10DBF7E8 /* UITests */, + 22F9F1514B91803BB4B88894 /* AppHooks */, + 337015ADFBA3AB96660DB3A6 /* Generated */, + 31CE4DA53232AA534057F912 /* Mocks */, + 4C826614718790C58C17117F /* UnitTests */, + ); + path = Sources; + sourceTree = ""; + }; + E6E1D07163F8752D62DA4A93 /* Styles */ = { + isa = PBXGroup; + children = ( + 89FBFC09F9DAFF1E4BA97849 /* FormButtonStyles.swift */, + ); + path = Styles; + sourceTree = ""; + }; + E703BBD16266053B8A193C7B /* RoomDetailsScreen */ = { + isa = PBXGroup; + children = ( + 6493AC9979CEB1410302BFE3 /* RoomDetailsScreenCoordinator.swift */, + 466C71A0FED9BFF287613C82 /* RoomDetailsScreenModels.swift */, + 837B440C4705E4B899BCB899 /* RoomDetailsScreenViewModel.swift */, + 63E8A1E8EE094F570573B6E8 /* RoomDetailsScreenViewModelProtocol.swift */, + 5DC032EC5F19009AA7CADB41 /* View */, + ); + path = RoomDetailsScreen; + sourceTree = ""; + }; + E71742A824A7192C8D378875 /* RoomDetailsEditScreen */ = { + isa = PBXGroup; + children = ( + 0A3E77399BD262D301451BF2 /* RoomDetailsEditScreenCoordinator.swift */, + 16D09C79746BDCD9173EB3A7 /* RoomDetailsEditScreenModels.swift */, + E413F4CBD7BF0588F394A9DD /* RoomDetailsEditScreenViewModel.swift */, + 1DF8F7A3AD83D04C08D75E01 /* RoomDetailsEditScreenViewModelProtocol.swift */, + 5F6CB68B44F6C587E463A934 /* View */, + ); + path = RoomDetailsEditScreen; + sourceTree = ""; + }; + E74CD7681375AD2EAA34D66B /* Authentication */ = { + isa = PBXGroup; + children = ( + CCACD75595C40EACD6AD4A74 /* AuthenticationTextFieldStyle.swift */, + 92390F9FA98255440A6BF5F8 /* OIDCAuthenticationPresenter.swift */, + 9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */, + 90F48FEF84016ED42A94BA24 /* LoginScreen */, + BA1938A75D8C780F694CEB62 /* ServerConfirmationScreen */, + 2D0D49B0533C4C2EB889BF3A /* ServerSelectionScreen */, + 5B2C520AB9863B8CBC8EB3CA /* SoftLogoutScreen */, + D847C12EC9B19A5FCDF2C815 /* WebRegistrationScreen */, + ); + path = Authentication; + sourceTree = ""; + }; + E816FC2BB467DD0B041C5A03 /* View */ = { + isa = PBXGroup; + children = ( + BFEA446F8618DBA79A9239CC /* MessageForwardingScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + EB5B1119B5AD79297F1D49EB /* AccountSettings */ = { + isa = PBXGroup; + children = ( + C1D737F4672021D0A7D218CD /* OIDCAccountSettingsPresenter.swift */, + ); + path = AccountSettings; + sourceTree = ""; + }; + EC4545C7E37E8294D3FE6800 /* StartChatScreen */ = { + isa = PBXGroup; + children = ( + B3005886F00029F058DB62BE /* StartChatScreenCoordinator.swift */, + B99E13633862847D8B7E2815 /* StartChatScreenModels.swift */, + 052B2F924572AFD70B5F500E /* StartChatScreenViewModel.swift */, + 78910787F967CBC6042A101E /* StartChatScreenViewModelProtocol.swift */, + A7F3784CAF9F4CF654BC52CD /* View */, + ); + path = StartChatScreen; + sourceTree = ""; + }; + EFD4F7FCAAAB3EF45EE7A067 /* BlockedUsersScreen */ = { + isa = PBXGroup; + children = ( + A16D0F226B1819D017531647 /* BlockedUsersScreenCoordinator.swift */, + 8642512079EEFD622E3AA66B /* BlockedUsersScreenModels.swift */, + A010B8EAD1A9F6B4686DF2F4 /* BlockedUsersScreenViewModel.swift */, + E76A706B3EEA32B882DA5E2D /* BlockedUsersScreenViewModelProtocol.swift */, + 2E035B978E415C77423FA3C2 /* View */, + ); + path = BlockedUsersScreen; + sourceTree = ""; + }; + F12966DF3DA87FEF21348D60 /* InviteUsersScreen */ = { + isa = PBXGroup; + children = ( + A861DA5932B128FE1DCB5CE2 /* InviteUsersScreenCoordinator.swift */, + 1454CF3AABD242F55C8A2615 /* InviteUsersScreenModels.swift */, + 02D155E09BF961BBA8F85263 /* InviteUsersScreenViewModel.swift */, + 22730A30C50AC2E3D5BA8642 /* InviteUsersScreenViewModelProtocol.swift */, + 493225D61FED2DA3D3B26104 /* View */, + ); + path = InviteUsersScreen; + sourceTree = ""; + }; + F3F90EBF3341F1FB47579B77 /* View */ = { + isa = PBXGroup; + children = ( + 598F01EBD0C4CC550C644418 /* AuthenticationStartLogo.swift */, + 24E8C8817F59BEC7E358EB78 /* AuthenticationStartScreen.swift */, + 50D685B4DB38BB5BD87C956A /* AuthenticationStartScreenBackgroundImage.swift */, + ); + path = View; + sourceTree = ""; + }; + F49710373735A3B8BB76DFF7 /* View */ = { + isa = PBXGroup; + children = ( + 56D6F88FE35A0979D2821E06 /* AppLockScreen.swift */, + 38345442415E07A931197C55 /* AppLockScreenPINKeypad.swift */, + ); + path = View; + sourceTree = ""; + }; + F526F4FE387B32380592BA53 /* NotificationPermissionsScreen */ = { + isa = PBXGroup; + children = ( + 91868EB98818044E6FEBE532 /* NotificationPermissionsScreenCoordinator.swift */, + 1DB2FC2AA9A07EE792DF65CF /* NotificationPermissionsScreenModels.swift */, + BE9BBB18FB27F09032AD8769 /* NotificationPermissionsScreenViewModel.swift */, + 20E69F67D2A70ABD08CA6D54 /* NotificationPermissionsScreenViewModelProtocol.swift */, + 9C0C1CB9E16302C00AB4956D /* View */, + ); + path = NotificationPermissionsScreen; + sourceTree = ""; + }; + F5A65D1D3B83593598DC278D /* EmojiPickerScreen */ = { + isa = PBXGroup; + children = ( + BEA38B9851CFCC4D67F5587D /* EmojiPickerScreenCoordinator.swift */, + F174A5627CDB3CAF280D1880 /* EmojiPickerScreenModels.swift */, + F3EAE3E9D5EF4A6D5D9C6CFD /* EmojiPickerScreenViewModel.swift */, + 11151E78D6BB2B04A8FBD389 /* EmojiPickerScreenViewModelProtocol.swift */, + 323160803A296713F839540B /* View */, + ); + path = EmojiPickerScreen; + sourceTree = ""; + }; + F6D661C666128C74BF0A7482 /* IdentityConfirmedScreen */ = { + isa = PBXGroup; + children = ( + 595EC503DA5517BBE6D39406 /* IdentityConfirmedScreenCoordinator.swift */, + 3DBE70FFB7936F35811772C1 /* IdentityConfirmedScreenModels.swift */, + 9C6624240FFD32B7F0834229 /* IdentityConfirmedScreenViewModel.swift */, + 8319173DD66C07F45DC48848 /* IdentityConfirmedScreenViewModelProtocol.swift */, + 6D7503E64A458DD09E65A3F7 /* View */, + ); + path = IdentityConfirmedScreen; + sourceTree = ""; + }; + F84100ED0C09031BAB7BB77E /* View */ = { + isa = PBXGroup; + children = ( + FB0D6CB491777E7FC6B5BA12 /* CreateRoomScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + FB039572AA54E0690B4051AD /* Common */ = { + isa = PBXGroup; + children = ( + D3F219838588C62198E726E3 /* LABiometryType.swift */, + ); + path = Common; + sourceTree = ""; + }; + FB4987F1C660F2085258866B /* View */ = { + isa = PBXGroup; + children = ( + 37FEE10AB666891E6A675E5E /* SecureBackupLogoutConfirmationScreen.swift */, + ); + path = View; + sourceTree = ""; + }; + FCDF06BDB123505F0334B4F9 /* Timeline */ = { + isa = PBXGroup; + children = ( + 190EC7285D3CFEF0D3011BCF /* GeoURI.swift */, + 0DF5CBAF69BDF5DF31C661E1 /* IntentionalMentions.swift */, + 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */, + 095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */, + 2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */, + 55AEEF8142DF1B59DB40FB93 /* TimelineItemSender.swift */, + F9E543072DE58E751F028998 /* TimelineProxy.swift */, + B50F03079F6B5EF9CA005F14 /* TimelineProxyProtocol.swift */, + 3EA31CC7012EA2A5653DAFC9 /* Fixtures */, + 2F2FED77226A43559F009463 /* TimelineController */, + 6B0910BCE4F1B02F124E1A09 /* TimelineItemContent */, + 95BE1C7CB2C80344FF0BE724 /* TimelineItems */, + ); + path = Timeline; + sourceTree = ""; + }; + FCE7249621F507F34A8122FB /* Audio */ = { + isa = PBXGroup; + children = ( + E44E35AA87F49503E7B3BF6E /* AudioConverter.swift */, + 2757B1BE23DF8AA239937243 /* AudioConverterProtocol.swift */, + BB284643AF7AB131E307DCE0 /* AudioSessionProtocol.swift */, + 3A2CAA4ABF5E66C3C8BBA3E9 /* Player */, + 0371482D36C95ABAF9D4C651 /* Recorder */, + ); + path = Audio; + sourceTree = ""; + }; + FDF04D0E125CB4B5C5DB5191 /* View */ = { + isa = PBXGroup; + children = ( + BCDA016D05107DED3B9495CB /* TimelineItemDebugView.swift */, + D53FCCE44F96E0BC411A6CF0 /* TimelineSenderAvatarView.swift */, + 93C713D124FE915ABF47A6B7 /* TimelineView.swift */, + 81F0325E252B057FAEEE1B2D /* TypingIndicatorView.swift */, + 505AE6F89590187813390D12 /* ItemMenu */, + C13DBC8C4A879A5A9C781BBD /* Polls */, + B470504BE2DC95FAC94FDD79 /* ReadReceipts */, + 7F6468993CB943953DC355A6 /* Replies */, + 308FE2283B9803DBBB05602C /* Style */, + 13CC0A77B6E5EEDF881C5E8B /* Supplementary */, + CC2B160BAFD5FEAC106F89F3 /* TimelineItemViews */, + ); + path = View; + sourceTree = ""; + }; + FFD7C58CA6A7D6BBC2F584B5 /* JoinRoomScreen */ = { + isa = PBXGroup; + children = ( + 3BDCCD2F6B405C14B9BCE94E /* JoinRoomScreenCoordinator.swift */, + 136F80A613B55BDD071DCEA5 /* JoinRoomScreenModels.swift */, + 1CD7C0A2750998C2D77AD00F /* JoinRoomScreenViewModel.swift */, + EEAB5662310AE73D93815134 /* JoinRoomScreenViewModelProtocol.swift */, + 6792D400AF30A6F2ACD426E4 /* View */, + ); + path = JoinRoomScreen; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 0E28CD62691FDBC63147D5E3 /* UITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = F1B67CF63C1231AEB14D70E6 /* Build configuration list for PBXNativeTarget "UITests" */; + buildPhases = ( + BAD5CD7BE53A7C832569B67A /* Sources */, + 86982BD498105258F3778110 /* Resources */, + CD30252A70288BD4BF476ED7 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 468963EFD503D7DFAD238754 /* PBXTargetDependency */, + ); + name = UITests; + packageProductDependencies = ( + B1E8B697DF78FE7F61FC6CA4 /* MatrixRustSDK */, + D661CAB418C075A94306A792 /* AnalyticsEvents */, + 4003BC24B24C9E63D3304177 /* DeviceKit */, + 36B7FC232711031AA2B0D188 /* DTCoreText */, + 78A5A8DE1E2B09C978C7F3B0 /* KeychainAccess */, + 50009897F60FAE7D63EF5E5B /* Kingfisher */, + A2AE110B053B55E38F8D10C7 /* KZFileWatchers */, + CCE5BF78B125320CBF3BB834 /* PostHog */, + 3853B78FB8531B83936C5DA6 /* SwiftState */, + 1BCD21310B997A6837B854D6 /* GZIP */, + 67E7A6F388D3BF85767609D9 /* Sentry */, + 21C83087604B154AA30E9A8F /* SnapshotTesting */, + BA93CD75CCE486660C9040BD /* Collections */, + 3FE40E79C36E7903121E6E3B /* SwiftOGG */, + ); + productName = UITests; + productReference = F506C6ADB1E1DA6638078E11 /* UITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; + 32C23C8D224D46EFE62AFAD0 /* UnitTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 79663128986C62EFAC289176 /* Build configuration list for PBXNativeTarget "UnitTests" */; + buildPhases = ( + 11F93544B4FC60F78F47D89C /* Sources */, + 9B3512762CF4A1D45A79C340 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 0EEC1557A40FBA6DF49D83A2 /* PBXTargetDependency */, + ); + name = UnitTests; + productName = UnitTests; + productReference = AAC9344689121887B74877AF /* UnitTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 7A17BE29BAC81ADBAC6349D9 /* PreviewTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = DA320DCEE4CFFAF3A564D280 /* Build configuration list for PBXNativeTarget "PreviewTests" */; + buildPhases = ( + 21960A0295DAB67E0015DD08 /* Sources */, + 91A7C1F08EC0DBF0B4357B36 /* Resources */, + C68A5D5A38E20DD51CF4B4FD /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 8E24DC048A099AAFEE13B4F5 /* PBXTargetDependency */, + ); + name = PreviewTests; + packageProductDependencies = ( + 7B6BC3219ADD8AA0311D2B86 /* SnapshotTesting */, + ); + productName = PreviewTests; + productReference = D95E8C0EFEC0C6F96EDAA71A /* PreviewTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + C0FAEB81CFD9776CD78CE489 /* ElementX */ = { + isa = PBXNativeTarget; + buildConfigurationList = B15427F8699AD5A5FC75C17E /* Build configuration list for PBXNativeTarget "ElementX" */; + buildPhases = ( + A7130911BCB2DF3D249A1836 /* ๐Ÿ›  SwiftGen */, + 7F26850DA7BC749F6FC41586 /* ๐Ÿง™ Sourcery - Generate mocks */, + 024F73AD10ACB163505ABE1E /* ๐Ÿง™ Sourcery - Generate preview tests */, + 9797D588420FCBBC228A63C9 /* Sources */, + 215E1D91B98672C856F559D0 /* Resources */, + EE878EAA342710DB973E0A87 /* Frameworks */, + 8E3CD0D0BB6697512E867C1D /* Embed Foundation Extensions */, + 98CA896D84BFD53B2554E891 /* โš ๏ธ SwiftLint */, + B35AB66424BB30087EEE408C /* ๐Ÿงน SwiftFormat */, + ); + buildRules = ( + ); + dependencies = ( + 2C29670603B37E38705D5FF1 /* PBXTargetDependency */, + ); + name = ElementX; + packageProductDependencies = ( + A678E40E917620059695F067 /* MatrixRustSDK */, + 07FEEEDB11543A7DED420F04 /* Compound */, + 290FDEDA4D764B9F7EBE55A9 /* Algorithms */, + 2A3F7BCCB18C15B30CCA39A9 /* AnalyticsEvents */, + 9C73F37731C9FDED1BB24C1C /* Collections */, + A7CA6F33C553805035C3B114 /* DeviceKit */, + 531CE4334AC5CA8DFF6AEB84 /* DTCoreText */, + 020597E28A4BC8E1BE8EDF6E /* KeychainAccess */, + 0DD568A494247444A4B56031 /* Kingfisher */, + 81DB3AB6CE996AB3954F4F03 /* KZFileWatchers */, + 1A6B622CCFDEFB92D9CF1CA5 /* LoremSwiftum */, + 1081D3630AAD3ACEDDEC3A98 /* LRUCache */, + C1BF15833233CD3BDB7E2B1D /* Mapbox */, + 4278261E147DB2DE5CFB7FC5 /* PostHog */, + 9573B94B1C86C6DF751AF3FD /* SwiftState */, + 997C7385E1A07E061D7E2100 /* GZIP */, + 7731767AE437BA3BD2CC14A8 /* Sentry */, + 75361A9D8A3C5501EADB225D /* SentrySwiftUI */, + A05AF81DDD14AD58CB0E1B9B /* Version */, + C05729B1684C331F5FFE9232 /* Emojibase */, + CA07D57389DACE18AEB6A5E2 /* WysiwygComposer */, + 391D11F92DFC91666AA1503F /* SwiftOGG */, + 2A4106A0A96DC4C273128AA5 /* DSWaveformImageViews */, + ); + productName = ElementX; + productReference = 4CD6AC7546E8D7E5C73CEA48 /* ElementX.app */; + productType = "com.apple.product-type.application"; + }; + D3DB351B7FBE0F49649171FC /* IntegrationTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = B7DCEF0CC298791B0EC4CA84 /* Build configuration list for PBXNativeTarget "IntegrationTests" */; + buildPhases = ( + D831C59C840FB7B2C1C028A0 /* Sources */, + C394D4118F7D345ABE288479 /* Resources */, + 60823A8E409E27661824D510 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 421359F1BC0A1816DD34A2BB /* PBXTargetDependency */, + ); + name = IntegrationTests; + packageProductDependencies = ( + C2C69B8BA5A9702E7A8BC08F /* MatrixRustSDK */, + BC01130651CB23340B899032 /* DeviceKit */, + 527578916BD388A09F5A8036 /* DTCoreText */, + 2B43F2AF7456567FE37270A7 /* KeychainAccess */, + DE8DC9B3FBA402117DC4C49F /* Kingfisher */, + 19CD5B074D7DD44AF4C58BB6 /* SwiftState */, + 2B788C81F6369D164ADEB917 /* GZIP */, + 886A0A498FA01E8EDD451D05 /* Sentry */, + A20EA00CCB9DBE0FFB17DD09 /* Collections */, + ); + productName = IntegrationTests; + productReference = 9C7F7DE62D33C6A26CBFCD72 /* IntegrationTests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; + FEB53A5BC378C913769656D8 /* NSE */ = { + isa = PBXNativeTarget; + buildConfigurationList = CBD61DB8FBC472BAA66A0CBD /* Build configuration list for PBXNativeTarget "NSE" */; + buildPhases = ( + 064584F7D1F4A58D753BDD96 /* Sources */, + 804B8DA568046249B1261739 /* Resources */, + BF59B36A7B2DB184B62826F6 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = NSE; + packageProductDependencies = ( + 6647C55D93508C7CE9D954A5 /* MatrixRustSDK */, + 800631D7250B7F93195035F1 /* KeychainAccess */, + 940C605265DD82DA0C655E23 /* Kingfisher */, + AD544C0FA48DFFB080920061 /* Collections */, + DCA3C4A997AD28E6918D4CE5 /* Compound */, + 385D4C28F9DC5CF53BD9ECDB /* DeviceKit */, + 593FBBF394712F2963E98A0B /* DTCoreText */, + 78B28D75FF7AF8E6146DEE2A /* LRUCache */, + 2B9ACE4FCACB5A8812154424 /* Version */, + ); + productName = NSE; + productReference = 0D8F620C8B314840D8602E3F /* NSE.appex */; + productType = "com.apple.product-type.app-extension"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + AC22997D58D612146053154D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1430; + ORGANIZATIONNAME = Element; + TargetAttributes = { + 0E28CD62691FDBC63147D5E3 = { + DevelopmentTeam = 7J4U792NQT; + TestTargetID = C0FAEB81CFD9776CD78CE489; + }; + 32C23C8D224D46EFE62AFAD0 = { + DevelopmentTeam = 7J4U792NQT; + }; + 7A17BE29BAC81ADBAC6349D9 = { + DevelopmentTeam = 7J4U792NQT; + }; + C0FAEB81CFD9776CD78CE489 = { + DevelopmentTeam = "$(DEVELOPMENT_TEAM)"; + }; + D3DB351B7FBE0F49649171FC = { + DevelopmentTeam = 7J4U792NQT; + TestTargetID = C0FAEB81CFD9776CD78CE489; + }; + F8E276FD6DC43EADB85241BC = { + DevelopmentTeam = 7J4U792NQT; + }; + FEB53A5BC378C913769656D8 = { + DevelopmentTeam = "$(DEVELOPMENT_TEAM)"; + }; + }; + }; + buildConfigurationList = 7AE41FCCF9D1352E2770D1F9 /* Build configuration list for PBXProject "ElementX" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + be, + bg, + cs, + de, + el, + en, + es, + et, + fr, + hu, + id, + it, + ka, + nl, + pl, + pt, + "pt-BR", + ro, + ru, + sk, + sv, + uk, + uz, + "zh-Hans", + "zh-Hant-TW", + ); + mainGroup = 405B00F139AEE3994601B36A; + packageReferences = ( + E025F19D013D9BA6C58B37F4 /* XCRemoteSwiftPackageReference "swift-algorithms" */, + AC3475112CA40C2C6E78D1EB /* XCRemoteSwiftPackageReference "matrix-analytics-events" */, + F76A08D0EA29A07A54F4EB4D /* XCRemoteSwiftPackageReference "swift-collections" */, + F71C70A4404CC6D9C4AF35F2 /* XCRemoteSwiftPackageReference "compound-ios" */, + 4C34425923978C97409A3EF2 /* XCRemoteSwiftPackageReference "DSWaveformImage" */, + C13F55E4518415CB4C278E73 /* XCRemoteSwiftPackageReference "DTCoreText" */, + D5F7D47BBAAE0CF1DDEB3034 /* XCRemoteSwiftPackageReference "DeviceKit" */, + 821C67C9A7F8CC3FD41B28B4 /* XCRemoteSwiftPackageReference "emojibase-bindings" */, + 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */, + 395DE6AE429B7ACC7C7FE31D /* XCRemoteSwiftPackageReference "KZFileWatchers" */, + 61916C63E3F5BD900F08DA0C /* XCRemoteSwiftPackageReference "KeychainAccess" */, + D283517192CAC3E2E6920765 /* XCRemoteSwiftPackageReference "Kingfisher" */, + CCD235515AFCEE6D2005B705 /* XCRemoteSwiftPackageReference "LRUCache" */, + 4BDA7F6042968E8422470F3F /* XCRemoteSwiftPackageReference "LoremSwiftum" */, + 0CBF57301AA172C21F76CE86 /* XCRemoteSwiftPackageReference "maplibre-gl-native-distribution" */, + 6FC4820D8D4559CEECA064D7 /* XCRemoteSwiftPackageReference "matrix-rust-components-swift" */, + 96495DD8554E2F39D3954354 /* XCRemoteSwiftPackageReference "posthog-ios" */, + A08925A9D5E3770DEB9D8509 /* XCRemoteSwiftPackageReference "sentry-cocoa" */, + E9C4F3A12AA1F65C13A8C8EB /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */, + E2F3DA35D462724CCC61DE2C /* XCRemoteSwiftPackageReference "swift-ogg" */, + 6582B5AF3F104B0F7E031E7D /* XCRemoteSwiftPackageReference "SwiftState" */, + EC6D0C817B1C21D9D096505A /* XCRemoteSwiftPackageReference "Version" */, + 44FA555384AD79668D886043 /* XCRemoteSwiftPackageReference "matrix-rich-text-editor-swift" */, + ); + projectDirPath = ""; + projectRoot = ""; + targets = ( + C0FAEB81CFD9776CD78CE489 /* ElementX */, + D3DB351B7FBE0F49649171FC /* IntegrationTests */, + FEB53A5BC378C913769656D8 /* NSE */, + F8E276FD6DC43EADB85241BC /* Periphery */, + 7A17BE29BAC81ADBAC6349D9 /* PreviewTests */, + 0E28CD62691FDBC63147D5E3 /* UITests */, + 32C23C8D224D46EFE62AFAD0 /* UnitTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 215E1D91B98672C856F559D0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 992F5E750F5030C4BA2D0D03 /* Assets.xcassets in Resources */, + 2CA6ABBC9A88EB89EA52FCCB /* ConfettiScene.scn in Resources */, + B6DA66EFC13A90846B625836 /* InfoPlist.strings in Resources */, + 5F5488FBC9CFEB6F433D74A4 /* Localizable.strings in Resources */, + 0EA6537A07E2DC882AEA5962 /* Localizable.stringsdict in Resources */, + 6860721DB3091BE08164C132 /* MapAssets.xcassets in Resources */, + 8B408C574E35E1C9B43A50CE /* PrivacyInfo.xcprivacy in Resources */, + C3317EF833AB4060988DF098 /* SAS.strings in Resources */, + 5FCD8AFA364206EE32B909A3 /* Settings.bundle in Resources */, + CE1694C7BB93C3311524EF28 /* Untranslated.strings in Resources */, + 2797C9D9BA642370F1C85D78 /* Untranslated.stringsdict in Resources */, + E67418DACEDBC29E988E6ACD /* message.caf in Resources */, + DFF7D6A6C26DDD40D00AE579 /* target.yml in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 804B8DA568046249B1261739 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7FED77802940EA7DF4D0D3A2 /* PrivacyInfo.xcprivacy in Resources */, + D2D70B5DB1A5E4AF0CD88330 /* target.yml in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 86982BD498105258F3778110 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 059173B3C77056C406906B6D /* target.yml in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 91A7C1F08EC0DBF0B4357B36 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FF9C06BBF6AC6F1CFFBEBFFC /* target.yml in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9B3512762CF4A1D45A79C340 /* Resources */ = { + 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 */, + 35E975CFDA60E05362A7CF79 /* target.yml in Resources */, + 87CEDB8A0696F0D5AE2ABB28 /* test_audio.mp3 in Resources */, + 21BF2B7CEDFE3CA67C5355AD /* test_image.png in Resources */, + E77469C5CD7F7F58C0AC9752 /* test_pdf.pdf in Resources */, + CBB4F39A1309F7281AE7AA8E /* test_voice_message.m4a in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C394D4118F7D345ABE288479 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9219640F4D980CFC5FE855AD /* target.yml in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 024F73AD10ACB163505ABE1E /* ๐Ÿง™ Sourcery - Generate preview tests */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "๐Ÿง™ Sourcery - Generate preview tests"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export PATH=\"$PATH:/opt/homebrew/bin\"\nif which sourcery >/dev/null; then\n sourcery --config Tools/Sourcery/PreviewTestsConfig.yml\nelse\n echo \"warning: Sourcery not installed, run swift run tools setup-project\"\nfi\n"; + }; + 23C8392ACDCF25131DAF6F9B /* Scan */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = Scan; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export PATH=\"$PATH:/opt/homebrew/bin\"\nperiphery scan --format xcode\n"; + }; + 7F26850DA7BC749F6FC41586 /* ๐Ÿง™ Sourcery - Generate mocks */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "๐Ÿง™ Sourcery - Generate mocks"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export PATH=\"$PATH:/opt/homebrew/bin\"\nif which sourcery >/dev/null; then\n sourcery --config Tools/Sourcery/AutoMockableConfig.yml\nelse\n echo \"warning: Sourcery not installed, run swift run tools setup-project\"\nfi\n"; + }; + 98CA896D84BFD53B2554E891 /* โš ๏ธ SwiftLint */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "โš ๏ธ SwiftLint"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export PATH=\"$PATH:/opt/homebrew/bin\"\nif which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; + }; + A7130911BCB2DF3D249A1836 /* ๐Ÿ›  SwiftGen */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "๐Ÿ›  SwiftGen"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export PATH=\"$PATH:/opt/homebrew/bin\"\nif which swiftgen >/dev/null; then\n swiftgen config run --config Tools/SwiftGen/swiftgen-config.yml\nelse\n echo \"warning: SwiftGen not installed, download from https://github.com/SwiftGen/SwiftGen\"\nfi\n"; + }; + B35AB66424BB30087EEE408C /* ๐Ÿงน SwiftFormat */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "๐Ÿงน SwiftFormat"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export PATH=\"$PATH:/opt/homebrew/bin\"\nif which swiftformat >/dev/null; then\n swiftformat --lint --lenient \"$PROJECT_DIR\"\nelse\n echo \"warning: SwiftFormat not installed, download from https://github.com/nicklockwood/SwiftFormat\"\nfi\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 064584F7D1F4A58D753BDD96 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A2172B5A26976F9174228B8A /* AppHooks.swift in Sources */, + 43F06DF42EC00B3CE2B020A4 /* AppSettings.swift in Sources */, + F253AAB4C8F06208173C9C4A /* Assets.swift in Sources */, + 484202C5D50983442D24D061 /* AttributedString.swift in Sources */, + CDCA8A559E098503DDE29477 /* AttributedStringBuilder.swift in Sources */, + BA43D782BE85C7F5F20C624A /* AttributedStringBuilderProtocol.swift in Sources */, + 968A5B890004526AB58A217C /* AvatarSize.swift in Sources */, + 9A3B0CDF097E3838FB1B9595 /* Bundle.swift in Sources */, + 238D561CA231339C6D4D06F3 /* ClientBuilder.swift in Sources */, + 0BAF83521871E69D222EE8E4 /* ClientBuilderHook.swift in Sources */, + 211B5F524E851178EE549417 /* CurrentValuePublisher.swift in Sources */, + B5618E3C948584E5C1F67033 /* DTHTMLElement+AttributedStringBuilder.swift in Sources */, + DFCA89C4EC2A5332ED6B441F /* DataProtectionManager.swift in Sources */, + 24A75F72EEB7561B82D726FD /* Date.swift in Sources */, + 9F11B9F347F9E2D236799FB3 /* ElementCallServiceConstants.swift in Sources */, + CFEC53440C572CEEABC4A6A0 /* ElementXAttributeScope.swift in Sources */, + A33784831AD880A670CAA9F9 /* FileManager.swift in Sources */, + 59F940FCBE6BC343AECEF75E /* ImageCache.swift in Sources */, + EBE13FAB4E29738AC41BD3E5 /* InfoPlistReader.swift in Sources */, + 8691186F9B99BCDDB7CACDD8 /* KeychainController.swift in Sources */, + A440D4BC02088482EC633A88 /* KeychainControllerProtocol.swift in Sources */, + FB0A9D06FC9122E37992D962 /* LayoutDirection.swift in Sources */, + AD2A81B65A9F6163012086F1 /* MXLog.swift in Sources */, + 52473A4D7B1FBD4CD1E770C8 /* MatrixEntityRegex.swift in Sources */, + 8B76191B9DDD1AC90A6E3A35 /* MediaFileHandleProxy.swift in Sources */, + 68184EF36396424FE19A727D /* MediaLoader.swift in Sources */, + 5D53AE9342A4C06B704247ED /* MediaLoaderProtocol.swift in Sources */, + 9DD5AA10E85137140FEA86A3 /* MediaProvider.swift in Sources */, + 7A642EE5F1ADC5D520F21924 /* MediaProviderProtocol.swift in Sources */, + E2DB696117BAEABAD5718023 /* MediaSourceProxy.swift in Sources */, + 4FC085B1E5D1EB804495E2F4 /* MockMediaProvider.swift in Sources */, + 5455147CAC63F71E48F7D699 /* NSELogger.swift in Sources */, + 30CC4F796B27BE8B1DFDBF5A /* NSEUserSession.swift in Sources */, + 1D5DC685CED904386C89B7DA /* NSRegularExpresion.swift in Sources */, + 94F0B78928E952689ACDB271 /* NetworkMonitor.swift in Sources */, + 4DEEFB73181C3B023DB42686 /* NetworkMonitorProtocol.swift in Sources */, + 5C02841B2A86327B2C377682 /* NotificationConstants.swift in Sources */, + 2689D22EF1D10D22B0A4DAEA /* NotificationContentBuilder.swift in Sources */, + 5D70FAE4D2BF4553AFFFFE41 /* NotificationItemProxy.swift in Sources */, + B89990DD875B0B603D4D4332 /* NotificationItemProxyProtocol.swift in Sources */, + B14BC354E56616B6B7D9A3D7 /* NotificationServiceExtension.swift in Sources */, + 62418EA4E3EB597AD184AEB6 /* PillConstants.swift in Sources */, + 55CDD3968D95D1A820B5491E /* PlaceholderAvatarImage.swift in Sources */, + F12F6BED7B6D7EE4BEE55039 /* PlainMentionBuilder.swift in Sources */, + 414F50CFCFEEE2611127DCFB /* RestorationToken.swift in Sources */, + 17BC15DA08A52587466698C5 /* RoomMessageEventStringBuilder.swift in Sources */, + 7354D094A4C59B555F407FA1 /* RustTracing.swift in Sources */, + 7573D682F089205F7F1D96CF /* SessionDirectories.swift in Sources */, + 422E8D182CA688D4565CD1E1 /* String.swift in Sources */, + 6EC7A40A537CFB3D526A111C /* Strings.swift in Sources */, + 719E7AAD1F8E68F68F30FECD /* Task.swift in Sources */, + E0FB26262689F04D66A949D7 /* TestablePreview.swift in Sources */, + 24DF253C18D3E2C56DD0E597 /* TracingConfiguration.swift in Sources */, + DDB47D29C6865669288BF87C /* UIFont+AttributedStringBuilder.m in Sources */, + 281BED345D59A9A6A99E9D98 /* UNNotificationContent.swift in Sources */, + 518C93DC6516D3D018DE065F /* UNNotificationRequest.swift in Sources */, + 06B55882911B4BF5B14E9851 /* URL.swift in Sources */, + D98B5EE8C4F5A2CE84687AE8 /* UTType.swift in Sources */, + 34357B287357BC0B9715DD51 /* UserAgentBuilder.swift in Sources */, + 3B28408450BCAED911283AA2 /* UserPreference.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 11F93544B4FC60F78F47D89C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C915347779B3C7FDD073A87A /* AVMetadataMachineReadableCodeObjectExtensionsTest.swift in Sources */, + A9A5801D5EE3D4D91F6DDADB /* AnalyticsSettingsScreenViewModelTests.swift in Sources */, + 890F0D453FE388756479AC97 /* AnalyticsTests.swift in Sources */, + 8478992479B296C45150208F /* AppLockScreenViewModelTests.swift in Sources */, + 77693820498ABF3508814D49 /* AppLockServiceTests.swift in Sources */, + 73F33E9776B7A50B65A031D2 /* AppLockSettingsScreenViewModelTests.swift in Sources */, + 4940B439681767BE9D78CFDB /* AppLockSetupBiometricsScreenViewModelTests.swift in Sources */, + 25C4C1100B6EA79F5CC7CBB5 /* AppLockSetupPINScreenViewModelTests.swift in Sources */, + 0EEC614342F823E5BF966C2C /* AppLockTimerTests.swift in Sources */, + EA78A7512AFB1E5451744EB1 /* AppRouteURLParserTests.swift in Sources */, + 3EC698F80DDEEFA273857841 /* ArrayTests.swift in Sources */, + 90DF83A6A347F7EE7EDE89EE /* AttributedStringBuilderTests.swift in Sources */, + 5100F53E6884A15F9BA07CC3 /* AttributedStringTests.swift in Sources */, + C1429699A6A5BB09A25775C1 /* AudioPlayerStateTests.swift in Sources */, + 3042527CB344A9EF1157FC26 /* AudioRecorderStateTests.swift in Sources */, + 192A3CDCD0174AD1E4A128E4 /* AudioRecorderTests.swift in Sources */, + 8ED8AF57A06F5EE9978ED23F /* AuthenticationStartScreenViewModelTests.swift in Sources */, + CEAEA57B7665C8E790599A78 /* BlockedUsersScreenViewModelTests.swift in Sources */, + 1B2F9F368619FFF8C63C87CC /* BugReportScreenViewModelTests.swift in Sources */, + 7F61F9ACD5EC9E845EF3EFBF /* BugReportServiceTests.swift in Sources */, + 366D5BFE52CB79E804C7D095 /* CallScreenViewModelTests.swift in Sources */, + FC8B95EC506E6BB5793D81CE /* ClientProtocolTests.swift in Sources */, + B5321A1F5B26A0F3EC54909E /* CollapsibleFlowLayoutTests.swift in Sources */, + 3A164187907DA43B7858F9EC /* CompletionSuggestionServiceTests.swift in Sources */, + 0C932A5158C1D0604DFC5750 /* ComposerToolbarViewModelTests.swift in Sources */, + D3FD96913D2B1AAA3149DAC7 /* CreateRoomViewModelTests.swift in Sources */, + CD0088B763CD970CF1CBF8CB /* DateTests.swift in Sources */, + 80F6C8EFCA4564B67F0D34B0 /* DeactivateAccountScreenViewModelTests.swift in Sources */, + 864C69CF951BF36D25BE0C03 /* DeveloperOptionsScreenViewModelTests.swift in Sources */, + F697284B9B5F2C00CFEA3B12 /* EmojiDetectionTests.swift in Sources */, + 25618589E0DE0F1E95FC7B5C /* EmojiProviderTests.swift in Sources */, + 71B62C48B8079D49F3FBC845 /* ExpiringTaskRunnerTests.swift in Sources */, + 07756D532EFE33DD1FA258E5 /* GeoURITests.swift in Sources */, + EE56238683BC3ECA9BA00684 /* GlobalSearchScreenViewModelTests.swift in Sources */, + 6817EAD73DC1FFD8B943B5B9 /* HomeScreenRoomTests.swift in Sources */, + F6F49E37272AD7397CD29A01 /* HomeScreenViewModelTests.swift in Sources */, + A23B8B27A1436A1049EEF68E /* InfoPlistReader.swift in Sources */, + A216C83ADCF32BA5EF8A6FBC /* InviteUsersViewModelTests.swift in Sources */, + 7C0E29E0279866C62EC67A28 /* JoinRoomScreenViewModelTests.swift in Sources */, + EEC40663922856C65D1E0DF5 /* KeychainControllerTests.swift in Sources */, + CC961529F9F1854BEC3272C9 /* LayoutMocks.swift in Sources */, + 8AC256AF0EC54658321C9241 /* LegalInformationScreenViewModelTests.swift in Sources */, + 0033481EE363E4914295F188 /* LocalizationTests.swift in Sources */, + 149D1942DC005D0485FB8D93 /* LoggingTests.swift in Sources */, + 1E59B77A0B2CE83DCC1B203C /* LoginViewModelTests.swift in Sources */, + 77C1A2F49CD90D3EFDF376E5 /* MapTilerURLBuildersTests.swift in Sources */, + 2E43A3D221BE9587BC19C3F1 /* MatrixEntityRegexTests.swift in Sources */, + 4B978C09567387EF4366BD7A /* MediaLoaderTests.swift in Sources */, + 3582056513A384F110EC8274 /* MediaPlayerProviderTests.swift in Sources */, + 167D00CAA13FAFB822298021 /* MediaProviderTests.swift in Sources */, + B9A8C34A00D03094C0CF56F3 /* MediaUploadPreviewScreenViewModelTests.swift in Sources */, + 23701DE32ACD6FD40AA992C3 /* MediaUploadingPreprocessorTests.swift in Sources */, + F777C6FEE7D106136E2ED2B2 /* MessageForwardingScreenViewModelTests.swift in Sources */, + 1146E9EDCF8344F7D6E0D553 /* MockCoder.swift in Sources */, + DC68E866D6E664B0D2B06E74 /* MockImageCache.swift in Sources */, + 981853650217B6C8ECDD998C /* NavigationRootCoordinatorTests.swift in Sources */, + 69C7B956B74BEC3DB88224EA /* NavigationSplitCoordinatorTests.swift in Sources */, + 4BB282209EA82015D0DF8F89 /* NavigationStackCoordinatorTests.swift in Sources */, + 1B2DADC008EE211AF1DA5292 /* NotificationManagerTests.swift in Sources */, + C11939FDC40716C4387275A4 /* NotificationSettingsEditScreenViewModelTests.swift in Sources */, + E3AC72E3E58F364EF15C1CC7 /* NotificationSettingsScreenViewModelTests.swift in Sources */, + 50381244BA280451771BE3ED /* PINTextFieldTests.swift in Sources */, + 1583E2D766E4485FF91662FC /* PermalinkTests.swift in Sources */, + 3982E60F9C126437D5E488A3 /* PillContextTests.swift in Sources */, + 2D2D8A53B35BE8D8A01449C6 /* PinnedEventsBannerStateTests.swift in Sources */, + FF7E8ECC8E7E1D1851517536 /* PollFormScreenViewModelTests.swift in Sources */, + D415764645491F10344FC6AC /* Publisher.swift in Sources */, + BDC4EB54CC3036730475CB8B /* QRCodeLoginScreenViewModelTests.swift in Sources */, + D53B80EF02C1062E68659EDD /* ReportContentViewModelTests.swift in Sources */, + 09D3D7D115318CAD131B4FE7 /* ResolveVerifiedUserSendFailureScreenViewModelTests.swift in Sources */, + C5627BCC3EBBB96A943B6D93 /* RestorationTokenTests.swift in Sources */, + 9B03943616A1147539DF7F08 /* RoomChangePermissionsScreenViewModelTests.swift in Sources */, + D2825E013A8ECFB66D9A1DE6 /* RoomChangeRolesScreenViewModelTests.swift in Sources */, + 9DD84E014ADFB2DD813022D5 /* RoomDetailsEditScreenViewModelTests.swift in Sources */, + EA974337FA7D040E7C74FE6E /* RoomDetailsViewModelTests.swift in Sources */, + 5B7D24A318AFF75AD611A026 /* RoomDirectorySearchScreenScreenViewModelTests.swift in Sources */, + 095D3906CF2F940C2D2D17CC /* RoomFlowCoordinatorTests.swift in Sources */, + 4C8C0C9FC10BA73AB7780534 /* RoomListFiltersStateTests.swift in Sources */, + 6B31508C6334C617360C2EAB /* RoomMemberDetailsViewModelTests.swift in Sources */, + 5D56CE09743C6B90C21B04C2 /* RoomMembersListScreenViewModelTests.swift in Sources */, + E49F74BD93230BDEFFE5EA51 /* RoomNotificationSettingsScreenViewModelTests.swift in Sources */, + 2335D1AB954C151FD8779F45 /* RoomPermissionsTests.swift in Sources */, + 7B1605C6FFD4D195F264A684 /* RoomPollsHistoryScreenViewModelTests.swift in Sources */, + 84C631E734FD2555B39B681C /* RoomRolesAndPermissionsScreenViewModelTests.swift in Sources */, + 46562110EE202E580A5FFD9C /* RoomScreenViewModelTests.swift in Sources */, + CC0D088F505F33A20DC5590F /* RoomStateEventStringBuilderTests.swift in Sources */, + 15913A5B07118C1268A840E4 /* RoomSummaryTests.swift in Sources */, + 7691233E3572A9173FD96CB3 /* SecureBackupKeyBackupScreenViewModelTests.swift in Sources */, + EB87DF90CF6F8D5D12404C6E /* SecureBackupLogoutConfirmationScreenViewModelTests.swift in Sources */, + 06B31F84CE52A7A7C271267C /* SecureBackupRecoveryKeyScreenViewModelTests.swift in Sources */, + 1B8E30B35BF8F541C1318F19 /* SecureBackupScreenViewModelTests.swift in Sources */, + 53A55748D5F587C9061F98BF /* ServerConfigurationScreenViewStateTests.swift in Sources */, + 89658A44C9FC19B58FD1C226 /* ServerConfirmationScreenViewModelTests.swift in Sources */, + 93875ADD456142D20823ED24 /* ServerSelectionViewModelTests.swift in Sources */, + CC1C948F67A5510A340FD7F0 /* SessionDirectoriesTests.swift in Sources */, + 86675910612A12409262DFBD /* SessionVerificationStateMachineTests.swift in Sources */, + 755727E0B756430DFFEC4732 /* SessionVerificationViewModelTests.swift in Sources */, + 206F0DBAB6AF042CA1FF2C0D /* SettingsViewModelTests.swift in Sources */, + 09AAF04B27732046C755D914 /* SoftLogoutViewModelTests.swift in Sources */, + 6189B4ABD535CE526FA1107B /* StartChatViewModelTests.swift in Sources */, + 9BB91CABB10D8FE90C491BCD /* StaticLocationScreenViewModelTests.swift in Sources */, + 1FEC0A4EC6E6DF693C16B32A /* StringTests.swift in Sources */, + E75CE800B3E64D0F7F8E228D /* TemplateScreenViewModelTests.swift in Sources */, + 3A7DD0D13B0FB8876D69D829 /* TextBasedRoomTimelineTests.swift in Sources */, + 0D4EB2ABAA5FE8CB10FDBCB8 /* TimelineItemFactoryTests.swift in Sources */, + 2F6207CB5C4715FE313B1E95 /* TimelineViewModelTests.swift in Sources */, + 282A5F3375DDC774AE09B0C3 /* TracingConfigurationTests.swift in Sources */, + 8E650379587C31D7912ED67B /* UNNotification+Creator.swift in Sources */, + AF33B9044498211C3D82F1E1 /* UNTextInputNotificationResponse+Creator.swift in Sources */, + 20C16A3F718802B0E4A19C83 /* URLComponentsTests.swift in Sources */, + 8D3E1FADD78E72504DE0E402 /* UserAgentBuilderTests.swift in Sources */, + E313BDD2B8813144139B2E00 /* UserDiscoveryServiceTest.swift in Sources */, + A1DF0E1E526A981ED6D5DF44 /* UserIndicatorControllerTests.swift in Sources */, + 04F17DE71A50206336749BAC /* UserPreferenceTests.swift in Sources */, + 73F547BEB41D3DAFAAF6E0AF /* UserProfileScreenViewModelTests.swift in Sources */, + 627139A3D79F032BA81E3A53 /* UserSessionFlowCoordinatorTests.swift in Sources */, + 81A7C020CB5F6232242A8414 /* UserSessionTests.swift in Sources */, + 21AFEFB8CEFE56A3811A1F5B /* VoiceMessageCacheTests.swift in Sources */, + 44BDD670FF9095ACE240A3A2 /* VoiceMessageMediaManagerTests.swift in Sources */, + A3D7110C1E75E7B4A73BE71C /* VoiceMessageRecorderTests.swift in Sources */, + 3116693C5EB476E028990416 /* XCTestCase.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 21960A0295DAB67E0015DD08 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 038AB2E86960FD240231D4C2 /* GeneratedPreviewTests.swift in Sources */, + ED635D7F00FA07E94D3CE1E8 /* PreviewTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9797D588420FCBBC228A63C9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 41F553349AF44567184822D8 /* APNSPayload.swift in Sources */, + CE3B7FC34FB2C279AAA5EA01 /* AVMetadataMachineReadableCodeObject.swift in Sources */, + 70394ECD2DCC70741538620D /* AccessibilityIdentifiers.swift in Sources */, + 34433A509DFEC93579B3B35B /* AdvancedSettingsScreen.swift in Sources */, + 4557192F5B15A8D9BB920232 /* AdvancedSettingsScreenCoordinator.swift in Sources */, + 0A194F5E70B5A628C1BF4476 /* AdvancedSettingsScreenModels.swift in Sources */, + B879446FD8E65A711EF8F9F7 /* AdvancedSettingsScreenViewModel.swift in Sources */, + 62910B515BCB4B455E24D7C1 /* AdvancedSettingsScreenViewModelProtocol.swift in Sources */, + 53C1E7F6A7D6409D89F36ED7 /* AggregatedReactionMock.swift in Sources */, + 4219391CD2351E410554B3E8 /* AggregratedReaction.swift in Sources */, + 64D05250CEDE8B604119F6E6 /* Alert.swift in Sources */, + 155063E980E763D4910EA3CF /* Analytics+SwiftUI.swift in Sources */, + F7567DD6635434E8C563BF85 /* AnalyticsClientProtocol.swift in Sources */, + 54C774874BED4A8FAD1F22FE /* AnalyticsConfiguration.swift in Sources */, + 8DDC6F28C797D8685F2F8E32 /* AnalyticsConsentState.swift in Sources */, + 24A1BBADAC43DC3F3A7347DA /* AnalyticsPromptScreen.swift in Sources */, + DCFE7CB3B9A104330BBB96AD /* AnalyticsPromptScreenCoordinator.swift in Sources */, + 6DC8E43BA04AC2AC4EB2EB97 /* AnalyticsPromptScreenModels.swift in Sources */, + DB65401349C143DFF883E2B0 /* AnalyticsPromptScreenViewModel.swift in Sources */, + 05BAB510CBC2ED35C154ADD0 /* AnalyticsPromptScreenViewModelProtocol.swift in Sources */, + 3C73442084BF8A6939F0F80B /* AnalyticsService.swift in Sources */, + 020F7E70167FB2833266F2F0 /* AnalyticsSettingsScreen.swift in Sources */, + 95690DDD9D547D3D842ACBE3 /* AnalyticsSettingsScreenCoordinator.swift in Sources */, + 7C6376192F578E0BA801BFEC /* AnalyticsSettingsScreenModels.swift in Sources */, + A74438ED16F8683A4B793E6A /* AnalyticsSettingsScreenViewModel.swift in Sources */, + 654E802C127B84554042903E /* AnalyticsSettingsScreenViewModelProtocol.swift in Sources */, + 8C1A5ECAF895D4CAF8C4D461 /* AppActivityView.swift in Sources */, + 077CB230153E072C94B1E6C3 /* AppAppearance.swift in Sources */, + 095C0ACFC234E0550A6404C5 /* AppCoordinator.swift in Sources */, + A021827B528F1EDC9101CA58 /* AppCoordinatorProtocol.swift in Sources */, + 4FF90E2242DBD596E1ED2E27 /* AppCoordinatorStateMachine.swift in Sources */, + 9D9690D2FD4CD26FF670620F /* AppDelegate.swift in Sources */, + 4CE638FD837ED72CD98AD9A9 /* AppHooks.swift in Sources */, + 6851B077B4C913CC12DB6E77 /* AppLockFlowCoordinator.swift in Sources */, + 06F8EDF52E33A2D36BCC1161 /* AppLockScreen.swift in Sources */, + 9912F9EB2D6589141A2957B4 /* AppLockScreenCoordinator.swift in Sources */, + 2DD9D0FE7CB5CFC80D071451 /* AppLockScreenModels.swift in Sources */, + 64E541F88F35BD126C4AFCA1 /* AppLockScreenPINKeypad.swift in Sources */, + 97969EF0B9C412CD38E5CA93 /* AppLockScreenViewModel.swift in Sources */, + E79D79CDAFE8BEBCC3AECA54 /* AppLockScreenViewModelProtocol.swift in Sources */, + 1D623953F970D11F6F38499C /* AppLockService.swift in Sources */, + D2048FD56760BDABA3DB5FC2 /* AppLockServiceProtocol.swift in Sources */, + BB9B800C6094E34860E89DC5 /* AppLockSetupBiometricsScreen.swift in Sources */, + 8015842CB4DE1BE414D2CDED /* AppLockSetupBiometricsScreenCoordinator.swift in Sources */, + 21813AF91CFC6F3E3896DB53 /* AppLockSetupBiometricsScreenModels.swift in Sources */, + 37906355E207DB5703754675 /* AppLockSetupBiometricsScreenViewModel.swift in Sources */, + 9FB41B0E8B2AA9B404E52C8B /* AppLockSetupBiometricsScreenViewModelProtocol.swift in Sources */, + B188D0907A4D38AAAF6FEFA8 /* AppLockSetupFlowCoordinator.swift in Sources */, + 733E2B19AB1FDA3B93293A28 /* AppLockSetupPINScreen.swift in Sources */, + 9696ECAFB4F0C079C5C2A526 /* AppLockSetupPINScreenCoordinator.swift in Sources */, + E4B07FF075C99D04D9AF792D /* AppLockSetupPINScreenModels.swift in Sources */, + 0F6C8033FA60CFD36F7CA205 /* AppLockSetupPINScreenViewModel.swift in Sources */, + 4C356F5CCB4CDC99BFA45185 /* AppLockSetupPINScreenViewModelProtocol.swift in Sources */, + 4E8A2A2CFEB212F14E49E1A1 /* AppLockSetupSettingsScreen.swift in Sources */, + 8DCD9CC5361FF22A5B2C20F1 /* AppLockSetupSettingsScreenCoordinator.swift in Sources */, + 6E4E401BE97AC241DA7C7716 /* AppLockSetupSettingsScreenModels.swift in Sources */, + 4807E8F51DB54F56B25E1C7E /* AppLockSetupSettingsScreenViewModel.swift in Sources */, + C85C7A201E4CFDA477ACEBEB /* AppLockSetupSettingsScreenViewModelProtocol.swift in Sources */, + EF890DEF0479E66548F2BA23 /* AppLockTimer.swift in Sources */, + 7A8B264506D3DDABC01B4EEB /* AppMediator.swift in Sources */, + A36AD251013402EDBD666C75 /* AppMediatorMock.swift in Sources */, + 4BBF6C8E3EFC944B55231B19 /* AppMediatorProtocol.swift in Sources */, + 355B11D08CE0CEF97A813236 /* AppRoutes.swift in Sources */, + 12CCA59536EDD99A3272CF77 /* AppSettings.swift in Sources */, + 4EAC427267424192964B16B3 /* AppSettingsHook.swift in Sources */, + 9462C62798F47E39DCC182D2 /* Application.swift in Sources */, + 61A36B9BB2ADE36CEFF5E98C /* Array.swift in Sources */, + 90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */, + 273AB64B9A26B61C51858867 /* AsyncSequence.swift in Sources */, + D7CDBAE82782BD0529DECB5F /* AttributedString.swift in Sources */, + 3ED2725734568F6B8CC87544 /* AttributedStringBuilder.swift in Sources */, + A6DEC1ADEC8FEEC206A0FA37 /* AttributedStringBuilderProtocol.swift in Sources */, + 2DA27D78560D5F79B917E163 /* AudioConverter.swift in Sources */, + F3F38062C6CA21CF403C5C90 /* AudioConverterProtocol.swift in Sources */, + 46C9F8FE3810A04A005FE16B /* AudioPlayer.swift in Sources */, + 086D01E79C8E8D3F004FAF21 /* AudioPlayerProtocol.swift in Sources */, + 1471A080552631358D152C18 /* AudioPlayerState.swift in Sources */, + 62A7FC3A0191BC7181AA432B /* AudioRecorder.swift in Sources */, + 3C31E1A65EEB61E72E1113B4 /* AudioRecorderProtocol.swift in Sources */, + 5992EF10AA157EBD97D88910 /* AudioRecorderState.swift in Sources */, + F8E725D42023ECA091349245 /* AudioRoomTimelineItem.swift in Sources */, + 88F348E2CB14FF71CBBB665D /* AudioRoomTimelineItemContent.swift in Sources */, + 7BD2123144A32F082CECC108 /* AudioRoomTimelineView.swift in Sources */, + 9278EC51D24E57445B290521 /* AudioSessionProtocol.swift in Sources */, + 8A6CB15C8FC68F557750BF54 /* AuthenticationClientBuilder.swift in Sources */, + 67E9926C4572C54F59FCA91A /* AuthenticationFlowCoordinator.swift in Sources */, + 9847B056C1A216C314D21E68 /* AuthenticationService.swift in Sources */, + 56DACDD379A86A1F5DEFE7BE /* AuthenticationServiceProtocol.swift in Sources */, + 9C55746D8F6A3E35CFCF4A7A /* AuthenticationStartLogo.swift in Sources */, + 7A170A5A4A352954BB2A1B96 /* AuthenticationStartScreen.swift in Sources */, + E4F924DECC66389C1C810550 /* AuthenticationStartScreenBackgroundImage.swift in Sources */, + A4AF12D9D8BA34B3B7B55B08 /* AuthenticationStartScreenCoordinator.swift in Sources */, + 0E3A2787C6AEC761A81A938A /* AuthenticationStartScreenModels.swift in Sources */, + E79B247A6DD28759636317EA /* AuthenticationStartScreenViewModel.swift in Sources */, + 874FEFB9D4A4AF447E0E086E /* AuthenticationStartScreenViewModelProtocol.swift in Sources */, + 6146996D5C4DDD5DA816FC87 /* AuthenticationTextFieldStyle.swift in Sources */, + 4AAA8606FBA290E23D15422E /* AvatarHeaderView.swift in Sources */, + D876EC0FED3B6D46C806912A /* AvatarSize.swift in Sources */, + 7A25D6926A2C01DB8D0D67A5 /* BadgeLabel.swift in Sources */, + A4B0BAD62A12ED76BD611B79 /* BadgeView.swift in Sources */, + 38546A6010A2CF240EC9AF73 /* BindableState.swift in Sources */, + EB9F4688006B52E69DF5358F /* BlankFormCoordinator.swift in Sources */, + 369BF960E52BBEE61F8A5BD1 /* BlockedUsersScreen.swift in Sources */, + 95E7B236F7116CACE05A6BC9 /* BlockedUsersScreenCoordinator.swift in Sources */, + 8C91D242BEEC657FABCC0B95 /* BlockedUsersScreenModels.swift in Sources */, + 934051B17A884AB0635DF81B /* BlockedUsersScreenViewModel.swift in Sources */, + A4B123C635F70DDD4BC2FAC9 /* BlockedUsersScreenViewModelProtocol.swift in Sources */, + 5EE1D4E316D66943E97FDCF2 /* BloomView.swift in Sources */, + B6DF6B6FA8734B70F9BF261E /* BlurHashDecode.swift in Sources */, + E794AB6ABE1FF5AF0573FEA1 /* BlurHashEncode.swift in Sources */, + A8FA7671948E3DF27F320026 /* BugReportFlowCoordinator.swift in Sources */, + F4C005F006FC3657B9F0A31D /* BugReportHook.swift in Sources */, + 6AD722DD92E465E56D2885AB /* BugReportScreen.swift in Sources */, + B98A20A093A4FB785BFCCA53 /* BugReportScreenCoordinator.swift in Sources */, + 4FFDC274824F7CC0BBDF581E /* BugReportScreenModels.swift in Sources */, + 8D71E5E53F372202379BECCE /* BugReportScreenViewModel.swift in Sources */, + B4A0C69370E6008A971463E7 /* BugReportScreenViewModelProtocol.swift in Sources */, + 3DA57CA0D609A6B37CA1DC2F /* BugReportService.swift in Sources */, + 172E6E9A612ADCF10A62CF13 /* BugReportServiceProtocol.swift in Sources */, + E1DF24D085572A55C9758A2D /* Bundle.swift in Sources */, + 6BAD956B909A6E29F6CC6E7C /* ButtonStyle.swift in Sources */, + 01B63F1A04A276B39AC17014 /* CallInviteRoomTimelineItem.swift in Sources */, + 3D72F5F9109AAA257542456B /* CallInviteRoomTimelineView.swift in Sources */, + E5AB28123E2488F97E953AC0 /* CallNotificationRoomTimelineItem.swift in Sources */, + 8A5064CAC8E5F3B18645621D /* CallNotificationRoomTimelineView.swift in Sources */, + D19A748E95E2FAB2940570F0 /* CallScreen.swift in Sources */, + 763D69741D58D2B650BC1FC9 /* CallScreenCoordinator.swift in Sources */, + B7C9E07F4F9CCC8DD7156A20 /* CallScreenModels.swift in Sources */, + 39A987B3E41B976D1DF944C6 /* CallScreenViewModel.swift in Sources */, + 84CAE3E96D93194DA06B9194 /* CallScreenViewModelProtocol.swift in Sources */, + BB6BF528BC7F5B87E08C4F18 /* CameraPicker.swift in Sources */, + E14E469CD97550D0FC58F3CA /* CancellableTask.swift in Sources */, + DF8F1211F2B0B56F0FCCA5C2 /* CertificateValidatorHook.swift in Sources */, + A52090A4FE0DB826578DFC03 /* Client.swift in Sources */, + C80E06ED97CE52704A46C148 /* ClientBuilder.swift in Sources */, + 87CEA3E07B602705BC2D2A20 /* ClientBuilderHook.swift in Sources */, + 6A0E7551E0D1793245F34CDD /* ClientError.swift in Sources */, + 1950A80CD198BED283DFC2CE /* ClientProxy.swift in Sources */, + DDFBDEE1DC32BDD5488F898C /* ClientProxyMock.swift in Sources */, + 24BDDD09A90B8BFE3793F3AA /* ClientProxyProtocol.swift in Sources */, + 0C797CD650DFD2876BEC5173 /* CollapsibleReactionLayout.swift in Sources */, + 78A3D84BA47DAC69B4D0A34C /* CollapsibleRoomTimelineView.swift in Sources */, + 0DC815CA24E1BD7F408F37D3 /* CollapsibleTimelineItem.swift in Sources */, + 663E198678778F7426A9B27D /* Collection.swift in Sources */, + 24B7CD41342C143117ADA768 /* Comparable.swift in Sources */, + 19DF5600A7F547B22DD7872A /* CompletionSuggestionService.swift in Sources */, + EAB3C1F0BC7F671ED8BDF82D /* CompletionSuggestionServiceProtocol.swift in Sources */, + 16E4F1B8B9BFE1367F96DDA7 /* CompletionSuggestionView.swift in Sources */, + 3AA9E878FDCFF85664AC071F /* ComposerDraftService.swift in Sources */, + 7856DE3EA4580AE0329986EB /* ComposerDraftServiceMock.swift in Sources */, + CB6956565D858C523E3E3B16 /* ComposerDraftServiceProtocol.swift in Sources */, + 937985546F708339711ECDFC /* ComposerToolbar.swift in Sources */, + 94E15D018D70563FA4AB4E5A /* ComposerToolbarModels.swift in Sources */, + 71AC1CAAC23403FFE847F2C9 /* ComposerToolbarViewModel.swift in Sources */, + 4A4110369DBB79E4A314F415 /* ComposerToolbarViewModelProtocol.swift in Sources */, + A6B83EB78F025D21B6EBA90C /* CompoundIcon.swift in Sources */, + EA6613B29BA671F39CE1B1D2 /* ConfirmationDialog.swift in Sources */, + AC7AA215D60FBC307F984028 /* Consumable.swift in Sources */, + C3522917C0C367C403429EEC /* CoordinatorProtocol.swift in Sources */, + 564BF06B3E93D6DD55F903B2 /* CreateRoomCoordinator.swift in Sources */, + C32765D740C81AD4C42E8F50 /* CreateRoomFlowParameters.swift in Sources */, + FB53CD9B74A15B3B94F9F788 /* CreateRoomModels.swift in Sources */, + 292827744227DF61C930BDDB /* CreateRoomScreen.swift in Sources */, + 0BE4D5CBF86956410F071F91 /* CreateRoomViewModel.swift in Sources */, + 4799A852132F1744E2825994 /* CreateRoomViewModelProtocol.swift in Sources */, + 565868808A1DA565707394ED /* CurrentValuePublisher.swift in Sources */, + A722F426FD81FC67706BB1E0 /* CustomLayoutLabelStyle.swift in Sources */, + 12C867E85E6D12EEDFD0B127 /* CustomStringConvertible.swift in Sources */, + C4F69156C31A447FEFF2A47C /* DTHTMLElement+AttributedStringBuilder.swift in Sources */, + 9905C1B1C6EFE38F3A6533F3 /* Data.swift in Sources */, + C6C06DDA8881260303FBA3A0 /* Date.swift in Sources */, + 244CB93DD7390379D905AFA8 /* DeactivateAccountScreen.swift in Sources */, + 564910A38858306301C1C21E /* DeactivateAccountScreenCoordinator.swift in Sources */, + 07F6382E29845D235BFA3308 /* DeactivateAccountScreenModels.swift in Sources */, + C9ABF75A43F2D26F1D9A1F27 /* DeactivateAccountScreenViewModel.swift in Sources */, + 4AD2B5426DBED97196AA4783 /* DeactivateAccountScreenViewModelProtocol.swift in Sources */, + EE8491AD81F47DF3C192497B /* DecorationTimelineItemProtocol.swift in Sources */, + 5780E444F405AA1304E1C23E /* DeveloperOptionsScreen.swift in Sources */, + 5DD85A0FE3D85AEC3C7EFE36 /* DeveloperOptionsScreenCoordinator.swift in Sources */, + 784592335560C2E91D32D177 /* DeveloperOptionsScreenModels.swift in Sources */, + B3D652AA1654270742072FB3 /* DeveloperOptionsScreenViewModel.swift in Sources */, + B9CB30FED3E29D2036EA3FCC /* DeveloperOptionsScreenViewModelProtocol.swift in Sources */, + 037006FB6DF1374F94E4058D /* Dictionary.swift in Sources */, + EDF8919F15DE0FF00EF99E70 /* DocumentPicker.swift in Sources */, + 4FDC8A9764CFDA90CE035725 /* Duration.swift in Sources */, + 2955F4C160CFD7794D819C64 /* EffectsScene.swift in Sources */, + AE1160076F663BF14E0E893A /* EffectsView.swift in Sources */, + FE4593FC2A02AAF92E089565 /* ElementAnimations.swift in Sources */, + 3118D9ABFD4BE5A3492FF88A /* ElementCallConfiguration.swift in Sources */, + 5732395A4F71F51F9C754C5A /* ElementCallService.swift in Sources */, + 3895969759E68FAB90C63EF7 /* ElementCallServiceConstants.swift in Sources */, + 8E7A902CA16E24928F83646C /* ElementCallServiceMock.swift in Sources */, + 48416BBEB8DDF3E4DED0EDB6 /* ElementCallServiceProtocol.swift in Sources */, + 07CC13C5729C24255348CBBD /* ElementCallWidgetDriver.swift in Sources */, + 370AF5BFCD4384DD455479B6 /* ElementCallWidgetDriverProtocol.swift in Sources */, + 3F997171C3C79A45E92BF9EF /* ElementWellKnown.swift in Sources */, + 7C1A7B594B2F8143F0DD0005 /* ElementXAttributeScope.swift in Sources */, + 7361B011A79BF723D8C9782B /* EmojiCategory.swift in Sources */, + E45C9FA22BC13B477FD3B4AC /* EmojiDetection.swift in Sources */, + D5C805F49B2C75DC3793E780 /* EmojiItem.swift in Sources */, + 3A08584ECDD4A4541DBF21F8 /* EmojiLoaderProtocol.swift in Sources */, + 340D39DB87F3800D53A6A621 /* EmojiPickerScreen.swift in Sources */, + C1910A16BDF131FECA77BE22 /* EmojiPickerScreenCoordinator.swift in Sources */, + EEB9C1555C63B93CA9C372C2 /* EmojiPickerScreenHeaderView.swift in Sources */, + 748F482FEF4E04D61C39AAD7 /* EmojiPickerScreenModels.swift in Sources */, + 2C5E832434EE94E21AB3B238 /* EmojiPickerScreenViewModel.swift in Sources */, + 1D69E31913DF66426985909B /* EmojiPickerScreenViewModelProtocol.swift in Sources */, + FBF09B6C900415800DDF2A21 /* EmojiProvider.swift in Sources */, + 5D27B6537591471A42C89027 /* EmoteRoomTimelineItem.swift in Sources */, + 8B41D0357B91CD3B6F6A3BCA /* EmoteRoomTimelineItemContent.swift in Sources */, + 661EF50C1F7D4B0BC8A7AAE3 /* EmoteRoomTimelineView.swift in Sources */, + 8B1D5CE017EEC734CF5FE130 /* Encodable.swift in Sources */, + 4C5A638DAA8AF64565BA4866 /* EncryptedRoomTimelineItem.swift in Sources */, + 709A9B52FC26B4CB86B8B020 /* EncryptedRoomTimelineView.swift in Sources */, + 03CDCA6243F89B194E3FAD17 /* EncryptionAuthenticity.swift in Sources */, + FBD402E3170EB1ED0D1AA672 /* EncryptionKeyProvider.swift in Sources */, + 46A6DB0F78FB399BD59E2D41 /* EncryptionKeyProviderProtocol.swift in Sources */, + 0C6DF318E9C8F6461E6ABDE7 /* EncryptionResetPasswordScreen.swift in Sources */, + 36926D795D6D19177C7812F8 /* EncryptionResetPasswordScreenCoordinator.swift in Sources */, + B1B255CE0E4306DD6E09D936 /* EncryptionResetPasswordScreenModels.swift in Sources */, + D6152E21036B88C44ECB22E7 /* EncryptionResetPasswordScreenViewModel.swift in Sources */, + A0601810597769B81C2358AF /* EncryptionResetPasswordScreenViewModelProtocol.swift in Sources */, + F3F9D61C53C348043D3D6F51 /* EncryptionResetScreen.swift in Sources */, + 3041EBA2660F28FFB7BDA339 /* EncryptionResetScreenCoordinator.swift in Sources */, + 97BAEDD9054FB5F233EE928B /* EncryptionResetScreenModels.swift in Sources */, + EC3320639828BED8B3E5F2C6 /* EncryptionResetScreenViewModel.swift in Sources */, + A0868BDE84D2140A885BE3C9 /* EncryptionResetScreenViewModelProtocol.swift in Sources */, + 50539366B408780B232C1910 /* EstimatedWaveformView.swift in Sources */, + F78BAD28482A467287A9A5A3 /* EventBasedMessageTimelineItemProtocol.swift in Sources */, + 02D8DF8EB7537EB4E9019DDB /* EventBasedTimelineItemProtocol.swift in Sources */, + EE57A96130DD8DB053790AE2 /* EventTimelineItemSDKMock.swift in Sources */, + 63E46D18B91D08E15FC04125 /* ExpiringTaskRunner.swift in Sources */, + 5F06AD3C66884CE793AE6119 /* FileManager.swift in Sources */, + D33AC79A50DFC26D2498DD28 /* FileRoomTimelineItem.swift in Sources */, + 37D789F24199B32E3FD1AA7B /* FileRoomTimelineItemContent.swift in Sources */, + 64EE9D2CF7AD02EE53983CE1 /* FileRoomTimelineView.swift in Sources */, + F5D2270B5021D521C0D22E11 /* FlowCoordinatorProtocol.swift in Sources */, + 18E3786918486D4C9726BC84 /* FormButtonStyles.swift in Sources */, + 4D0F4385B7DDB68C66C78857 /* FormattedBodyText.swift in Sources */, + 7807B1DEE32617896886A8E5 /* FormattingToolbar.swift in Sources */, + 46BA7F4B4D3A7164DED44B88 /* FullscreenDialog.swift in Sources */, + F18CA61A58C77C84F551B8E7 /* GeneratedMocks.swift in Sources */, + 63780F9DA06573E38A471ECA /* GenericCallLinkWidgetDriver.swift in Sources */, + 4295E5F850897710A51AE114 /* GeoURI.swift in Sources */, + F0DACC95F24128A54CD537E4 /* GlobalSearchScreen.swift in Sources */, + 9F11E743EA01482E78A438B0 /* GlobalSearchScreenCell.swift in Sources */, + 7D261B5119E78CC8E771CA15 /* GlobalSearchScreenCoordinator.swift in Sources */, + D34E328E9E65904358248FDD /* GlobalSearchScreenModels.swift in Sources */, + 55D18AA4F4A2257642EBDB94 /* GlobalSearchScreenViewModel.swift in Sources */, + E32A18802EB37EEE3EF7B965 /* GlobalSearchScreenViewModelProtocol.swift in Sources */, + D4D5595C4A2A702CFF4E94FF /* HeroImage.swift in Sources */, + 0C1E537A49ABB386F7554D4A /* HighlightedTimelineItemModifier.swift in Sources */, + 964B9D2EC38C488C360CE0C9 /* HomeScreen.swift in Sources */, + 62C5876C4254C58C2086F0DE /* HomeScreenContent.swift in Sources */, + 8CC12086CBF91A7E10CDC205 /* HomeScreenCoordinator.swift in Sources */, + 77BB228AEA861E50FFD6A228 /* HomeScreenEmptyStateView.swift in Sources */, + 22C5483D01EEB290B8339817 /* HomeScreenInviteCell.swift in Sources */, + 8810A2A30A68252EBB54EE05 /* HomeScreenModels.swift in Sources */, + B04E9EB589CE99C3929E817A /* HomeScreenRecoveryKeyConfirmationBanner.swift in Sources */, + 0AE0AB1952F186EB86719B4F /* HomeScreenRoomCell.swift in Sources */, + A10D6CCDE2010C09EEA1A593 /* HomeScreenRoomList.swift in Sources */, + 0A0625A271EE5B06D2AAA069 /* HomeScreenSlidingSyncMigrationBanner.swift in Sources */, + DE4F8C4E0F1DB4832F09DE97 /* HomeScreenViewModel.swift in Sources */, + 56F0A22972A3BB519DA2261C /* HomeScreenViewModelProtocol.swift in Sources */, + 2BBE320EE426A347AAE5C7DA /* IdentityConfirmationScreen.swift in Sources */, + C3BB6887CF13B19182E81F87 /* IdentityConfirmationScreenCoordinator.swift in Sources */, + 77574A519A4E484880053EAD /* IdentityConfirmationScreenModels.swift in Sources */, + 0C346A4AD174F441EDB1414E /* IdentityConfirmationScreenViewModel.swift in Sources */, + 489BB6A733D3DA0FE7062650 /* IdentityConfirmationScreenViewModelProtocol.swift in Sources */, + 9C4EC28A921486B1775D7F8C /* IdentityConfirmedScreen.swift in Sources */, + 93AC1E8418D8C827671FB3A9 /* IdentityConfirmedScreenCoordinator.swift in Sources */, + D22345698F6548C1EE960940 /* IdentityConfirmedScreenModels.swift in Sources */, + 01681E8B20AD6F0D237F2DC1 /* IdentityConfirmedScreenViewModel.swift in Sources */, + AADE7C2497A7B55D8BED7BD6 /* IdentityConfirmedScreenViewModelProtocol.swift in Sources */, + BA31448FBD9697F8CB9A83CD /* ImageCache.swift in Sources */, + 7CD16990BA843BE9ED639129 /* ImageRoomTimelineItem.swift in Sources */, + B796A25F282C0A340D1B9C12 /* ImageRoomTimelineItemContent.swift in Sources */, + E2D57361B835E4D2230960E6 /* ImageRoomTimelineView.swift in Sources */, + B6048166B4AA4CEFEA9B77A6 /* InfoPlistReader.swift in Sources */, + BFEB24336DFD5F196E6F3456 /* IntentionalMentions.swift in Sources */, + 2AAB2A77F1762A2648078A30 /* InteractiveQuickLook.swift in Sources */, + C4D2BCAA54E2C62B94B24AF4 /* InviteUsersScreen.swift in Sources */, + E27C4D1A1F8BB77CA790B403 /* InviteUsersScreenCoordinator.swift in Sources */, + C26DB49C06C00B5DF1A991A5 /* InviteUsersScreenModels.swift in Sources */, + 61941DEE5F3834765770BE01 /* InviteUsersScreenSelectedItem.swift in Sources */, + F519DE17A3A0F760307B2E6D /* InviteUsersScreenViewModel.swift in Sources */, + A17FAD2EBC53E17B5FD384DB /* InviteUsersScreenViewModelProtocol.swift in Sources */, + 89B909AC66B96FA054EF3C14 /* InvitedRoomProxy.swift in Sources */, + 6A54F52443EC52AC5CD772C0 /* JoinRoomScreen.swift in Sources */, + AFE2AB612A1460E49578D746 /* JoinRoomScreenCoordinator.swift in Sources */, + DEDBD3E9CFCC9F20CAC79881 /* JoinRoomScreenModels.swift in Sources */, + EF47D802A404A53F15D5D4B6 /* JoinRoomScreenViewModel.swift in Sources */, + 7B66DA4E7E5FE4D1A0FCEAA4 /* JoinRoomScreenViewModelProtocol.swift in Sources */, + 261261778DEFAEFC042B875E /* JoinedRoomProxy.swift in Sources */, + 7D249465ED00988EEEC14E05 /* JoinedRoomProxyMock.swift in Sources */, + E3CA565A4B9704F191B191F0 /* JoinedRoomSize+MemberCount.swift in Sources */, + 1FE593ECEC40A43789105D80 /* KeychainController.swift in Sources */, + FD29471C72872F8B7580E3E1 /* KeychainControllerMock.swift in Sources */, + CB99B0FA38A4AC596F38CC13 /* KeychainControllerProtocol.swift in Sources */, + 454F8DDC4442C0DE54094902 /* LABiometryType.swift in Sources */, + E468CC731C3F4D678499E52F /* LAContextMock.swift in Sources */, + D5681C80D8281560AACE0035 /* Label.swift in Sources */, + EEAE954289DE813A61656AE0 /* LayoutDirection.swift in Sources */, + 42B084FDE621FBEE433AF444 /* LegalInformationScreen.swift in Sources */, + 9EBDC79CAC9B63A0D626E333 /* LegalInformationScreenCoordinator.swift in Sources */, + F40B097470D3110DFDB1FAAA /* LegalInformationScreenModels.swift in Sources */, + BDED6DA7AD1E76018C424143 /* LegalInformationScreenViewModel.swift in Sources */, + A9D349478F7D4A2B1E40CEF9 /* LegalInformationScreenViewModelProtocol.swift in Sources */, + 6E47D126DD7585E8F8237CE7 /* LoadableAvatarImage.swift in Sources */, + D9F80CE61BF8FF627FDB0543 /* LoadableImage.swift in Sources */, + 256D76972BA3254F7CB7F88B /* LocationAnnotation.swift in Sources */, + B5479997ECC516C121E6625E /* LocationMarkerView.swift in Sources */, + D46C33F8B61B55F0C8C2D15F /* LocationRoomTimelineItem.swift in Sources */, + 854E82E064BA53CD0BC45600 /* LocationRoomTimelineItemContent.swift in Sources */, + 973C48F9E4EFB808F61BE401 /* LocationRoomTimelineView.swift in Sources */, + 29491EE7AE37E239E839C5A3 /* LocationSharingScreenModels.swift in Sources */, + 36DE961B784087D5E18EF9BA /* LogViewerScreen.swift in Sources */, + CF38B70D8C6DD42C00A56A27 /* LogViewerScreenCoordinator.swift in Sources */, + 5518DA4A6C9B4FC4B497EA9A /* LogViewerScreenModels.swift in Sources */, + A6F345328CCC5C9B0DAE2257 /* LogViewerScreenViewModel.swift in Sources */, + 558E2673B04FDD06A1A12DD3 /* LogViewerScreenViewModelProtocol.swift in Sources */, + 872A6457DF573AF8CEAE927A /* LoginHomeserver.swift in Sources */, + CEB8FB1269DE20536608B957 /* LoginMode.swift in Sources */, + 5375902175B2FEA2949D7D74 /* LoginScreen.swift in Sources */, + 651341E67C3514F9811A1EC1 /* LoginScreenCoordinator.swift in Sources */, + C5A07E2D88BE7D51DCECD166 /* LoginScreenModels.swift in Sources */, + BDA68E8D95B2B24B28825B8B /* LoginScreenViewModel.swift in Sources */, + A5B9EF45C7B8ACEB4954AE36 /* LoginScreenViewModelProtocol.swift in Sources */, + B10F7D5C237417DA160F4603 /* LongPressWithFeedback.swift in Sources */, + B94368839BDB69172E28E245 /* MXLog.swift in Sources */, + C1D0AB8222D7BAFC9AF9C8C0 /* MapLibreMapView.swift in Sources */, + C9BE065FA7D4E77E4C61CB69 /* MapLibreModels.swift in Sources */, + E2DDA49BD62F03F180A42E30 /* MapLibreStaticMapView.swift in Sources */, + D181AC8FF236B7F91C0A8C28 /* MapTiler.swift in Sources */, + FCDA202B246F75BA28E10C5F /* MapTilerAuthorization.swift in Sources */, + D6661A94DBD97658B2ADBD6A /* MapTilerStaticMap.swift in Sources */, + 7B5DAB915357BE596529BF25 /* MapTilerStaticMapProtocol.swift in Sources */, + 83A4DAB181C56987C3E804FF /* MapTilerStyle.swift in Sources */, + 14343C2F9AD2BFEA92CA28FF /* MapTilerStyleBuilder.swift in Sources */, + BEA646DF302711A753F0D420 /* MapTilerStyleBuilderProtocol.swift in Sources */, + 67C05C50AD734283374605E3 /* MatrixEntityRegex.swift in Sources */, + 8658F5034EAD7357CE7F9AC7 /* MatrixUserShareLink.swift in Sources */, + BCC864190651B3A3CF51E4DF /* MediaFileHandleProxy.swift in Sources */, + 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 */, + 30CC1DB7CE357659C82AA115 /* MediaProviderProtocol.swift in Sources */, + 5897A59DDBD3592282092223 /* MediaSourceProxy.swift in Sources */, + C67FCC854F3A6FC7A2EC04D0 /* MediaUploadPreviewScreen.swift in Sources */, + C8BD80891BAD688EF2C15CDB /* MediaUploadPreviewScreenCoordinator.swift in Sources */, + 3B0F9B57D25B07E66F15762A /* MediaUploadPreviewScreenModels.swift in Sources */, + A969147E0EEE0E27EE226570 /* MediaUploadPreviewScreenViewModel.swift in Sources */, + 9B872FF37DBE6BE054903831 /* MediaUploadPreviewScreenViewModelProtocol.swift in Sources */, + 8A0BD60CA4A6004DB06B5403 /* MediaUploadingPreprocessor.swift in Sources */, + 8C706DA7EAC0974CA2F8F1CD /* MentionBuilder.swift in Sources */, + F669B55BC237CDA5EC9332FE /* MentionSuggestionItemView.swift in Sources */, + 64AB99285DC4437C0DDE9585 /* MenuSheetLabelStyle.swift in Sources */, + D6DE764B17FB4A9A12C33BF4 /* MessageComposer.swift in Sources */, + 2118E35D312951B241067BD5 /* MessageComposerTextField.swift in Sources */, + C8E0FA0FF2CD6613264FA6B9 /* MessageForwardingScreen.swift in Sources */, + 2BBA132149DEBED6624084A8 /* MessageForwardingScreenCoordinator.swift in Sources */, + 695825D20A761C678809345D /* MessageForwardingScreenModels.swift in Sources */, + F54E2D6CAD96E1AC15BC526F /* MessageForwardingScreenViewModel.swift in Sources */, + C13128AAA787A4C2CBE4EE82 /* MessageForwardingScreenViewModelProtocol.swift in Sources */, + C97325EFDCCEE457432A9E82 /* MessageText.swift in Sources */, + 32FC143630CE22A9E403370B /* MockAuthenticationService.swift in Sources */, + B659E3A49889E749E3239EA7 /* MockMediaProvider.swift in Sources */, + 09C83DDDB07C28364F325209 /* MockRoomTimelineController.swift in Sources */, + B721125D17A0BA86794F29FB /* MockServerSelectionScreenState.swift in Sources */, + AF2ABA2794E376B64104C964 /* MockSoftLogoutScreenState.swift in Sources */, + F9842667B68DC6FA1F9ECCBB /* NSItemProvider.swift in Sources */, + EA01A06EEDFEF4AE7652E5F3 /* NSRegularExpresion.swift in Sources */, + FA2BBAE9FC5E2E9F960C0980 /* NavigationCoordinators.swift in Sources */, + 71C1347F23868324A4F43940 /* NavigationModule.swift in Sources */, + B5E455C9689EA600EDB3E9E0 /* NavigationRootCoordinator.swift in Sources */, + 93BAF04D9CCBC0A8841414D0 /* NetworkMonitor.swift in Sources */, + 96B3606E30F824095B1DD022 /* NetworkMonitorMock.swift in Sources */, + 865DD5CA474C6AE6C2BC008E /* NetworkMonitorProtocol.swift in Sources */, + 0C58A846F61949B1D545D661 /* NoticeRoomTimelineItem.swift in Sources */, + 9408CE8B8865C0C8DD4C9869 /* NoticeRoomTimelineItemContent.swift in Sources */, + 7F825CBD857D65DC986087BA /* NoticeRoomTimelineView.swift in Sources */, + 3F70E237CE4C3FAB02FC227F /* NotificationConstants.swift in Sources */, + CE9530A4CA661E090635C2F2 /* NotificationItemProxy.swift in Sources */, + FD4C21F8DA1E273DE94FCD1A /* NotificationItemProxyProtocol.swift in Sources */, + 652ACCF104A8CEF30788963C /* NotificationManager.swift in Sources */, + 06D3942496E9E0E655F14D21 /* NotificationManagerProtocol.swift in Sources */, + 5139F4BD5A5DF6F8D11A9BDE /* NotificationPermissionsScreen.swift in Sources */, + 454311EAC17D778E19F46592 /* NotificationPermissionsScreenCoordinator.swift in Sources */, + 3E7B65C2C97748D5D65AAA8B /* NotificationPermissionsScreenModels.swift in Sources */, + D4D7CCECC6C0AAFC42E165BB /* NotificationPermissionsScreenViewModel.swift in Sources */, + C8A9C595038AFA2D707AC8C1 /* NotificationPermissionsScreenViewModelProtocol.swift in Sources */, + C0090506A52A1991BAF4BA68 /* NotificationSettingsChatType.swift in Sources */, + AA93B3F9B5DD097DEF79F981 /* NotificationSettingsEditScreen.swift in Sources */, + 53A59720F4729D9BBFFB7CAB /* NotificationSettingsEditScreenCoordinator.swift in Sources */, + 4EA1CE0E88EA68E862FF0EA2 /* NotificationSettingsEditScreenModels.swift in Sources */, + 119AE9A3FC6E0606C1146528 /* NotificationSettingsEditScreenRoomCell.swift in Sources */, + D5FE90A6AF5FD5AE91BD37C7 /* NotificationSettingsEditScreenViewModel.swift in Sources */, + 2F623DA1122140A987B34D08 /* NotificationSettingsEditScreenViewModelProtocol.swift in Sources */, + B93FA0DA1504B301CAEE141B /* NotificationSettingsProxy.swift in Sources */, + 4BAB8222DBA0B4207D1223E0 /* NotificationSettingsProxyMock.swift in Sources */, + A1BA8D6BABAFA9BAAEAA3FFD /* NotificationSettingsProxyProtocol.swift in Sources */, + 6786C4B0936AC84D993B20BF /* NotificationSettingsScreen.swift in Sources */, + F6DFA23885980118AD7359C5 /* NotificationSettingsScreenCoordinator.swift in Sources */, + D12F440F7973F1489F61389D /* NotificationSettingsScreenModels.swift in Sources */, + 7F7EA51A9A43125A8CB6AC90 /* NotificationSettingsScreenViewModel.swift in Sources */, + CBD2ABE4C1A47ECD99E1488E /* NotificationSettingsScreenViewModelProtocol.swift in Sources */, + 523C6800ED85D5810CF18C19 /* OIDCAccountSettingsPresenter.swift in Sources */, + 9A4E3D5AA44B041DAC3A0D81 /* OIDCAuthenticationPresenter.swift in Sources */, + E362924A42934C9F0F97A956 /* OIDCConfigurationProxy.swift in Sources */, + 11A6B8E3CBDBF0A4107FF4CE /* OnboardingFlowCoordinator.swift in Sources */, + 3CE4C5071B6D2576E2473989 /* OrderedSet.swift in Sources */, + AA5924D3B67F7ACD98BBEFDC /* OrientationManagerProtocol.swift in Sources */, + 804C15D8ADE0EA7A5268F58A /* OverridableAvatarImage.swift in Sources */, + CD6A72B65D3B6076F4045C30 /* PHGPostHogConfiguration.swift in Sources */, + 6F86349BDEAF4495EAE38931 /* PHGPostHogMock.swift in Sources */, + F7D709D7ECABE46641BB8B6B /* PHGPostHogProtocol.swift in Sources */, + 847DE3A7EB9FCA2C429C6E85 /* PINTextField.swift in Sources */, + 7501442D52A65F73DF79FFD4 /* PaginationIndicatorRoomTimelineItem.swift in Sources */, + BC7CA1379D7C24F47B1B8B7E /* PaginationIndicatorRoomTimelineView.swift in Sources */, + 962A4F8AD6312804E2C6BB6E /* PhotoLibraryPicker.swift in Sources */, + EE4E2C1922BBF5169E213555 /* PillAttachmentViewProvider.swift in Sources */, + 899359A4D1147601F6C4E364 /* PillConstants.swift in Sources */, + 767D366C40F1311CFA333763 /* PillContext.swift in Sources */, + 7708976CEE6AFB5CFAEFBA68 /* PillTextAttachment.swift in Sources */, + 8C050A8012E6078BEAEF5BC8 /* PillTextAttachmentData.swift in Sources */, + 7E2BB42805C59DB57E95610F /* PillView.swift in Sources */, + 9CBB04365408F9D6F46BA3A7 /* PinnedEventsTimelineFlowCoordinator.swift in Sources */, + 5D52925FEB1B780C65B0529F /* PinnedEventsTimelineScreen.swift in Sources */, + E184FFAD32342D3D6E2F89AA /* PinnedEventsTimelineScreenCoordinator.swift in Sources */, + FEC03105D1BDE0F49BD7F243 /* PinnedEventsTimelineScreenModels.swift in Sources */, + 5F0B5797D1BFF2A51084B4C3 /* PinnedEventsTimelineScreenViewModel.swift in Sources */, + 7B3A59786DB2F741A1743ED0 /* PinnedEventsTimelineScreenViewModelProtocol.swift in Sources */, + 053B8BD2496207838878C6C9 /* PinnedItemsBannerView.swift in Sources */, + D26093BB80B69092B0E9AC7C /* PinnedItemsIndicatorView.swift in Sources */, + 9D79B94493FB32249F7E472F /* PlaceholderAvatarImage.swift in Sources */, + 1BA04D05EBC6646958B1BE60 /* PlaceholderScreenCoordinator.swift in Sources */, + EF0D0155DD104C7A41A2EB0E /* PlainMentionBuilder.swift in Sources */, + ED564C8C7C43CF5F67000368 /* PlatformViewVersionPredicate.swift in Sources */, + B79E8AB83EBBDCD476D0362F /* PollFormScreen.swift in Sources */, + 3DAD62988F072607441CB7A5 /* PollFormScreenCoordinator.swift in Sources */, + 70B83D44043293B4B77440B9 /* PollFormScreenModels.swift in Sources */, + F9EA79092C18A8CFE4922DD2 /* PollFormScreenViewModel.swift in Sources */, + 260FFC1475EE94F641C3F3F9 /* PollFormScreenViewModelProtocol.swift in Sources */, + 151D2477F75782C8702F2873 /* PollInteractionHandler.swift in Sources */, + 915B4CDAF220D9AEB4047D45 /* PollInteractionHandlerProtocol.swift in Sources */, + 16CBD087038DE3815CDA512C /* PollMock.swift in Sources */, + 4716587A9BA69ED8FD1B986B /* PollOptionView.swift in Sources */, + 864C0D3A4077BF433DBC691F /* PollRoomTimelineItem.swift in Sources */, + 128FFD8A3D85845F9A927F47 /* PollRoomTimelineView.swift in Sources */, + 1307268DC41730E5BCF7D9A0 /* PollView.swift in Sources */, + DF504B10A4918F971A57BEF2 /* PostHogAnalyticsClient.swift in Sources */, + FD4DEC88210F35C35B2FB386 /* ProcessInfo.swift in Sources */, + 69DE29C3E3180BB17D840690 /* ProgressCursorModifier.swift in Sources */, + C7ABEBECDC513F7887DACF66 /* ProgressMaskModifier.swift in Sources */, + 9B356742E035D90A8BB5CABE /* ProposedViewSize.swift in Sources */, + 2835FD52F3F618D07F799B3D /* Publisher.swift in Sources */, + 4949C8C12669D1B5E082366E /* QRCodeLoginScreen.swift in Sources */, + 4D23D41B8109E010304050F8 /* QRCodeLoginScreenCoordinator.swift in Sources */, + 46FCD999E92D9717D24AAB94 /* QRCodeLoginScreenModels.swift in Sources */, + 30E5628F74AD3C27A061BF25 /* QRCodeLoginScreenViewModel.swift in Sources */, + E9D2ED1C4186931E3D5FDA4E /* QRCodeLoginScreenViewModelProtocol.swift in Sources */, + C8C7AF33AADF88B306CD2695 /* QRCodeLoginService.swift in Sources */, + BB04B1D8E7401C90506D401E /* QRCodeLoginServiceProtocol.swift in Sources */, + FDD5B4B616D9FF4DE3E9A418 /* QRCodeScannerView.swift in Sources */, + C9A631FD968249B4BA0B7B3C /* ReactionsSummaryView.swift in Sources */, + 743790BF6A5B0577EA74AF14 /* ReadMarkerRoomTimelineItem.swift in Sources */, + 2BBC0EB1E07963810A5D7423 /* ReadMarkerRoomTimelineView.swift in Sources */, + 91ABC91758A6E4A5FAA2E9C4 /* ReadReceipt.swift in Sources */, + ABD29E06DD1224812E750AF8 /* ReadReceiptCell.swift in Sources */, + 1653275750CE11F5CE94DDFD /* ReadReceiptsSummaryView.swift in Sources */, + C76892321558E75101E68ED6 /* ReadableFrameModifier.swift in Sources */, + AF19D65A9C60C6B2646F3210 /* RedactedRoomTimelineItem.swift in Sources */, + 8CFDA5F1562479CB3A34D277 /* RedactedRoomTimelineView.swift in Sources */, + C413D36D44F89DE63D3ADFA4 /* ReportContentScreen.swift in Sources */, + C1A5C386319835FB0C77736B /* ReportContentScreenCoordinator.swift in Sources */, + 46A261AA898344A1F3C406B1 /* ReportContentScreenModels.swift in Sources */, + 42A5A42ACF063EEE6B1980D2 /* ReportContentScreenViewModel.swift in Sources */, + 8285FF4B2C2331758C437FF7 /* ReportContentScreenViewModelProtocol.swift in Sources */, + 4715FE33667C5899E64DD0E6 /* ResolveVerifiedUserSendFailureScreen.swift in Sources */, + 583A41A4BE76E2E9E0B97881 /* ResolveVerifiedUserSendFailureScreenCoordinator.swift in Sources */, + 108D3C0707A90B0F848CDBB9 /* ResolveVerifiedUserSendFailureScreenModels.swift in Sources */, + 9A0326D2375075871D2AB537 /* ResolveVerifiedUserSendFailureScreenViewModel.swift in Sources */, + ED3E91E6166E4923791ACA84 /* ResolveVerifiedUserSendFailureScreenViewModelProtocol.swift in Sources */, + A494741843F087881299ACF0 /* RestorationToken.swift in Sources */, + 6E391F7F628D984AF44385D9 /* RoomAttachmentPicker.swift in Sources */, + 8587A53DE8EF94FD796DC375 /* RoomAvatarImage.swift in Sources */, + F8C87130FD999F7F1076208C /* RoomChangePermissionsScreen.swift in Sources */, + 86F9D3028A1F4AE819D75560 /* RoomChangePermissionsScreenCoordinator.swift in Sources */, + 4D4D236F0BBCDC4D2CBCCBB5 /* RoomChangePermissionsScreenModels.swift in Sources */, + 241CDEFE23819867D9B39066 /* RoomChangePermissionsScreenViewModel.swift in Sources */, + FEFD5290B31FCBA6999912C8 /* RoomChangePermissionsScreenViewModelProtocol.swift in Sources */, + 832A4EA1094B8FE423A08700 /* RoomChangeRolesScreen.swift in Sources */, + 244407B18B2F2D6466BA5961 /* RoomChangeRolesScreenCoordinator.swift in Sources */, + 7FF6E1FBE6E9517FD29A1D8E /* RoomChangeRolesScreenModels.swift in Sources */, + 7F941B063C94E1718DFC2CF3 /* RoomChangeRolesScreenRow.swift in Sources */, + CDAE3A37D4DF136F9D07DB61 /* RoomChangeRolesScreenSection.swift in Sources */, + BD6685592716CA957D7BAAC4 /* RoomChangeRolesScreenSelectedItem.swift in Sources */, + 3EC5A41F9FB7DD63A4DC6144 /* RoomChangeRolesScreenViewModel.swift in Sources */, + 4E36A66E0EDA74BF3A036FD0 /* RoomChangeRolesScreenViewModelProtocol.swift in Sources */, + 859E2CA2EDF343BD24DE52EB /* RoomDetails.swift in Sources */, + 0BDA19079FD6E17C5AC62E22 /* RoomDetailsEditScreen.swift in Sources */, + E78D429F18071545BF661A52 /* RoomDetailsEditScreenCoordinator.swift in Sources */, + A6D4C5EEA85A6A0ABA1559D6 /* RoomDetailsEditScreenModels.swift in Sources */, + 659E5B766F76FDEC1BF393A4 /* RoomDetailsEditScreenViewModel.swift in Sources */, + C49FCC766673006B6D299F1C /* RoomDetailsEditScreenViewModelProtocol.swift in Sources */, + 126EE01D8BEAEF26105D83C5 /* RoomDetailsScreen.swift in Sources */, + FA5A7E32B1920FCB4EEDC1BA /* RoomDetailsScreenCoordinator.swift in Sources */, + DB079D1929B5A5F52D207C83 /* RoomDetailsScreenModels.swift in Sources */, + A5D551E5691749066E0E0C44 /* RoomDetailsScreenViewModel.swift in Sources */, + E9560744F7B0292E20ECE5F2 /* RoomDetailsScreenViewModelProtocol.swift in Sources */, + DDE7B4771452300C103B1EB8 /* RoomDirectoryCell.swift in Sources */, + 2B97BCE72D86645F1485C976 /* RoomDirectorySearchMock.swift in Sources */, + 10D60D287025B71F4743A425 /* RoomDirectorySearchProxy.swift in Sources */, + D5B1531A72387D432939D4E0 /* RoomDirectorySearchProxyProtocol.swift in Sources */, + 904F06C9C1AEF884C2077542 /* RoomDirectorySearchScreen.swift in Sources */, + 02A92F8F4538CECDFB4F2607 /* RoomDirectorySearchScreenCoordinator.swift in Sources */, + 49500BBA1CD65A5AE252D970 /* RoomDirectorySearchScreenModels.swift in Sources */, + 91C6AC0E9D2B9C0C76CC6AD4 /* RoomDirectorySearchScreenScreenModelProtocol.swift in Sources */, + 1DC227816777A2F3A19657E5 /* RoomDirectorySearchScreenViewModel.swift in Sources */, + 2814E7075BF3A5C0CCBC9F90 /* RoomDirectorySearchView.swift in Sources */, + 42F1C8731166633E35A6D7E6 /* RoomEventStringBuilder.swift in Sources */, + D55AF9B5B55FEED04771A461 /* RoomFlowCoordinator.swift in Sources */, + 04A16B45228F7678A027C079 /* RoomHeaderView.swift in Sources */, + 8A83D715940378B9BA9F739E /* RoomInviterLabel.swift in Sources */, + F4996C82A4B3A5FF0C8EDD03 /* RoomListFilterModels.swift in Sources */, + 4A9CEEE612D6D8B3DDBD28BA /* RoomListFilterView.swift in Sources */, + BD0BE20DBCE31253AE4490A1 /* RoomListFiltersEmptyStateView.swift in Sources */, + 33F1FB19F222BA9930AB1A00 /* RoomListFiltersView.swift in Sources */, + 8DC176CC5ABA24138EB443DD /* RoomMemberDetails.swift in Sources */, + 19FE025AE9BA2959B6589B0D /* RoomMemberDetailsScreen.swift in Sources */, + 899793EFC63DF93C3E0141E7 /* RoomMemberDetailsScreenCoordinator.swift in Sources */, + A816F7087C495D85048AC50E /* RoomMemberDetailsScreenModels.swift in Sources */, + EAF2B3E6C6AEC4AD3A8BD454 /* RoomMemberDetailsScreenViewModel.swift in Sources */, + 5B6E5AD224509E6C0B520D6E /* RoomMemberDetailsScreenViewModelProtocol.swift in Sources */, + 6448F8D1D3CA4CD27BB4CADD /* RoomMemberProxy.swift in Sources */, + 92D9088B901CEBB1A99ECA4E /* RoomMemberProxyMock.swift in Sources */, + F118DD449066E594F63C697D /* RoomMemberProxyProtocol.swift in Sources */, + 5DD0EF30070DC0A82C5CCD33 /* RoomMembersListManageMemberSheet.swift in Sources */, + C08AAE7563E0722C9383F51C /* RoomMembersListScreen.swift in Sources */, + 1C9BB74711E5F24C77B7FED0 /* RoomMembersListScreenCoordinator.swift in Sources */, + A975D60EA49F6AF73308809F /* RoomMembersListScreenMemberCell.swift in Sources */, + 8944548A684F1C837CEC47F4 /* RoomMembersListScreenModels.swift in Sources */, + F3E2D3F7ACDED65A4E5CD8DE /* RoomMembersListScreenViewModel.swift in Sources */, + C4078364FD9FA00EA9D00A15 /* RoomMembersListScreenViewModelProtocol.swift in Sources */, + D5E771132BB36240DE38102F /* RoomMessageEventStringBuilder.swift in Sources */, + 83B17A44D3E7E6DF22D9A2A4 /* RoomModerationRole.swift in Sources */, + C9F5B48D15B9BCAE1F8D564E /* RoomNotificationModeProxy.swift in Sources */, + 0180C44B997EDA8D21F883AC /* RoomNotificationSettingsCustomSectionView.swift in Sources */, + CE6F237360875D3D573FD0B2 /* RoomNotificationSettingsProxy.swift in Sources */, + 8544657DEEE717ED2E22E382 /* RoomNotificationSettingsProxyMock.swift in Sources */, + EF5009AC03212227131C8AF2 /* RoomNotificationSettingsProxyProtocol.swift in Sources */, + C7774720A4B2E34693E3227C /* RoomNotificationSettingsScreen.swift in Sources */, + 13CBC470FB619A6393A21908 /* RoomNotificationSettingsScreenCoordinator.swift in Sources */, + 6E63704717F17593A475D152 /* RoomNotificationSettingsScreenModels.swift in Sources */, + E9347F56CF0683208F4D9249 /* RoomNotificationSettingsScreenViewModel.swift in Sources */, + BA4C9049BC96DED3A2F3B82E /* RoomNotificationSettingsScreenViewModelProtocol.swift in Sources */, + 491D62ACD19E6F134B1766AF /* RoomNotificationSettingsUserDefinedScreen.swift in Sources */, + DBC8D1DBFE9F9CA7662BC8AA /* RoomPermissions.swift in Sources */, + 7A02EB29F3B993AB20E0A198 /* RoomPollsHistoryScreen.swift in Sources */, + E58F1F3276E98A93F7D39219 /* RoomPollsHistoryScreenCoordinator.swift in Sources */, + 51B3B19FA5F91B455C807BA7 /* RoomPollsHistoryScreenModels.swift in Sources */, + 79741C1953269FF1A211D246 /* RoomPollsHistoryScreenViewModel.swift in Sources */, + F103924DED414ADFE398CE99 /* RoomPollsHistoryScreenViewModelProtocol.swift in Sources */, + FA9C427FFB11B1AA2DCC5602 /* RoomProxyProtocol.swift in Sources */, + DC77E9DB2CFBE84A2BDF20C5 /* RoomRolesAndPermissionsFlowCoordinator.swift in Sources */, + D10BA4F041DC58580A440A32 /* RoomRolesAndPermissionsScreen.swift in Sources */, + B13774779EA19FDD7A35A4A8 /* RoomRolesAndPermissionsScreenCoordinator.swift in Sources */, + 8358D145F9BF94F412BEDCA8 /* RoomRolesAndPermissionsScreenModels.swift in Sources */, + 69B3C6010B42010F591FC3CB /* RoomRolesAndPermissionsScreenViewModel.swift in Sources */, + F8F47CE757EE656905F01F2C /* RoomRolesAndPermissionsScreenViewModelProtocol.swift in Sources */, + C55A44C99F64A479ABA85B46 /* RoomScreen.swift in Sources */, + A851635B3255C6DC07034A12 /* RoomScreenCoordinator.swift in Sources */, + 352C439BE0F75E101EF11FB1 /* RoomScreenModels.swift in Sources */, + 7BB31E67648CF32D2AB5E502 /* RoomScreenViewModel.swift in Sources */, + 617624A97BDBB75ED3DD8156 /* RoomScreenViewModelProtocol.swift in Sources */, + 6C34237AFB808E38FC8776B9 /* RoomStateEventStringBuilder.swift in Sources */, + 59C41313AED7566C3AC51163 /* RoomSummary.swift in Sources */, + 983896D611ABF52A5C37498D /* RoomSummaryProvider.swift in Sources */, + B5899F18AD6C56CE08FE532B /* RoomSummaryProviderMock.swift in Sources */, + AA050DF4AEE54A641BA7CA22 /* RoomSummaryProviderProtocol.swift in Sources */, + 2ABF11717C64054CEF2819A3 /* RoomTimelineController.swift in Sources */, + 38896D54D6D675534E606195 /* RoomTimelineControllerFactory.swift in Sources */, + B31E5493C99381D4E204438B /* RoomTimelineControllerFactoryMock.swift in Sources */, + 7ECF12D5DCD69F67BD3E3842 /* RoomTimelineControllerFactoryProtocol.swift in Sources */, + E89536FC8C0E4B79E9842A78 /* RoomTimelineControllerProtocol.swift in Sources */, + 4E945AD6862C403F74E57755 /* RoomTimelineItemFactory.swift in Sources */, + 13C77FDF17C4C6627CFFC205 /* RoomTimelineItemFactoryProtocol.swift in Sources */, + 70558528EF68CAAEF09972D5 /* RoomTimelineItemFixtures.swift in Sources */, + 878070573C7BF19E735707B4 /* RoomTimelineItemProperties.swift in Sources */, + 1AE4AEA0FA8DEF52671832E0 /* RoomTimelineItemProtocol.swift in Sources */, + AD55E245FE686D7DB4C86406 /* RoomTimelineItemView.swift in Sources */, + 41CE5E1289C8768FC5B6490C /* RoomTimelineItemViewState.swift in Sources */, + 9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */, + B272E5D1DE8BDA87A6B7A696 /* RoomTimelineProviderMock.swift in Sources */, + 77D7DAA41AAB36800C1F2E2D /* RoomTimelineProviderProtocol.swift in Sources */, + B2F8E01ABA1BA30265B4ECBE /* RoundedCornerShape.swift in Sources */, + BD11E639CF566A9DA8FCA717 /* RoundedLabelItem.swift in Sources */, + 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 */, + 67160204A8D362BB7D4AD259 /* Search.swift in Sources */, + 339BC18777912E1989F2F17D /* Section.swift in Sources */, + F833D5B5BE6707F961FA88DB /* SecureBackupController.swift in Sources */, + 0C88044649BAEE6C49BFC43A /* SecureBackupControllerProtocol.swift in Sources */, + 21F29351EDD7B2A5534EE862 /* SecureBackupKeyBackupScreen.swift in Sources */, + 5BC6C4ADFE7F2A795ECDE130 /* SecureBackupKeyBackupScreenCoordinator.swift in Sources */, + B7888FC1E1DEF816D175C8D6 /* SecureBackupKeyBackupScreenModels.swift in Sources */, + 1795EA6A6C4942CAE0459DF0 /* SecureBackupKeyBackupScreenViewModel.swift in Sources */, + A4C29D373986AFE4559696D5 /* SecureBackupKeyBackupScreenViewModelProtocol.swift in Sources */, + B6064D82FCDCB829601C1F59 /* SecureBackupLogoutConfirmationScreen.swift in Sources */, + 5AE6404C4FD4848ACCFF9EDC /* SecureBackupLogoutConfirmationScreenCoordinator.swift in Sources */, + D0A965852D6C04138FA55181 /* SecureBackupLogoutConfirmationScreenModels.swift in Sources */, + 92720AB0DA9AB5EEF1DAF56B /* SecureBackupLogoutConfirmationScreenViewModel.swift in Sources */, + D050D7756E92CA061ED0ABF0 /* SecureBackupLogoutConfirmationScreenViewModelProtocol.swift in Sources */, + FA71CD334F2D2289BEF0D749 /* SecureBackupRecoveryKeyScreen.swift in Sources */, + B1387648C6F71F1B98244803 /* SecureBackupRecoveryKeyScreenCoordinator.swift in Sources */, + 8AA84EF202F2EFC8453A97BD /* SecureBackupRecoveryKeyScreenModels.swift in Sources */, + 27F015B0D5436633B5B3C8C3 /* SecureBackupRecoveryKeyScreenViewModel.swift in Sources */, + F0570F1ECD70C4C851FB2052 /* SecureBackupRecoveryKeyScreenViewModelProtocol.swift in Sources */, + E84ADFE9696936C18C2424B5 /* SecureBackupScreen.swift in Sources */, + E77FE06B165A38BF1735509F /* SecureBackupScreenCoordinator.swift in Sources */, + DA7E867F5EAFF8E20B2EE3B6 /* SecureBackupScreenModels.swift in Sources */, + 7BF368A78E6D9AFD222F25AF /* SecureBackupScreenViewModel.swift in Sources */, + AC90434798E7894370E80E66 /* SecureBackupScreenViewModelProtocol.swift in Sources */, + 14E99D27628B1A6F0CB46FEA /* SeparatorRoomTimelineItem.swift in Sources */, + 5341D48F833E3E30F16FA2A3 /* SeparatorRoomTimelineView.swift in Sources */, + 2E8C6672D0EE7D5B1BEDB8E2 /* ServerConfirmationScreen.swift in Sources */, + 5894C2514400A4FBC9327632 /* ServerConfirmationScreenCoordinator.swift in Sources */, + 401BB28CD6B7DD6B4E7863E7 /* ServerConfirmationScreenModels.swift in Sources */, + F0A26CD502C3A5868353B0FA /* ServerConfirmationScreenViewModel.swift in Sources */, + FD762761C5D0C30E6255C3D8 /* ServerConfirmationScreenViewModelProtocol.swift in Sources */, + 43F35A7E5703D64DB0519C59 /* ServerSelectionScreen.swift in Sources */, + E5F4C992845388B50BABACAA /* ServerSelectionScreenCoordinator.swift in Sources */, + 6530865EB9A8C0F0AF0216DA /* ServerSelectionScreenModels.swift in Sources */, + 85F89F3F320F4FADCFFFE68B /* ServerSelectionScreenViewModel.swift in Sources */, + 0C47AE2CA7929CB3B0E2D793 /* ServerSelectionScreenViewModelProtocol.swift in Sources */, + BD782053BE4C3D2F0BDE5699 /* ServiceLocator.swift in Sources */, + 914BDF61447C723F104BCE33 /* SessionDirectories.swift in Sources */, + 237FC70AA257B935F53316BA /* SessionVerificationControllerProxy.swift in Sources */, + AE1A73B24D63DA3D63DC4EE3 /* SessionVerificationControllerProxyMock.swift in Sources */, + 94A65DD8A353DF112EBEF67A /* SessionVerificationControllerProxyProtocol.swift in Sources */, + 707E49BE07E8EB8A13C0EB1E /* SessionVerificationScreen.swift in Sources */, + D02DEB36D32A72A1B365E452 /* SessionVerificationScreenCoordinator.swift in Sources */, + 5710AAB27D5D866292C1FE06 /* SessionVerificationScreenModels.swift in Sources */, + 601AB75BD52B0B4276CEB84A /* SessionVerificationScreenStateMachine.swift in Sources */, + 4A8287E5281B44A8754BE509 /* SessionVerificationScreenViewModel.swift in Sources */, + 762DB0973865293F0C3D3D7B /* SessionVerificationScreenViewModelProtocol.swift in Sources */, + 755395927DDD6EBDDA5E217A /* SettingsFlowCoordinator.swift in Sources */, + 34F1261CEF6D6A00D559B520 /* SettingsScreen.swift in Sources */, + AF8BFA37791E1756EE243E08 /* SettingsScreenCoordinator.swift in Sources */, + B93D7CE520088AD53FA6D53C /* SettingsScreenModels.swift in Sources */, + E0B6A569AC3E81D233B43D60 /* SettingsScreenViewModel.swift in Sources */, + A009BDFB0A6816D4C392ADCB /* SettingsScreenViewModelProtocol.swift in Sources */, + 1C8BC70A18060677E295A846 /* ShareToMapsAppActivity.swift in Sources */, + 274CE3C986841D15FD530BF5 /* ShimmerModifier.swift in Sources */, + 77920AFA8091AC6B9F190C90 /* Signposter.swift in Sources */, + F08F7BC07CA9AEF5CD157918 /* Snapshotting.swift in Sources */, + 8BC8EF6705A78946C1F22891 /* SoftLogoutScreen.swift in Sources */, + A3A7A05E8F9B7EB0E1A09A2A /* SoftLogoutScreenCoordinator.swift in Sources */, + F86102DC2C68BBBB0521BAAE /* SoftLogoutScreenModels.swift in Sources */, + F37629BAA5E8F50AAF2A131D /* SoftLogoutScreenViewModel.swift in Sources */, + CF4044A8EED5C41BC0ED6ABE /* SoftLogoutScreenViewModelProtocol.swift in Sources */, + DF004A5B2EABBD0574D06A04 /* SplashScreenCoordinator.swift in Sources */, + 3DAF325D8AE461F7CDB282BD /* StartChatScreen.swift in Sources */, + 6CD61FAF03E8986523C2ABB8 /* StartChatScreenCoordinator.swift in Sources */, + C051475DFF4C8EBDDF4DC8E4 /* StartChatScreenModels.swift in Sources */, + 4A85928E27D4C1A548A06EE9 /* StartChatScreenViewModel.swift in Sources */, + B402708F8728DD0DB7C324E2 /* StartChatScreenViewModelProtocol.swift in Sources */, + CB6BCBF28E4B76EA08C2926D /* StateRoomTimelineItem.swift in Sources */, + 3B277D9538090766DA6C4566 /* StateRoomTimelineView.swift in Sources */, + B4AAB3257A83B73F53FB2689 /* StateStoreViewModel.swift in Sources */, + B1069F361E604D5436AE9FFD /* StaticLocationScreen.swift in Sources */, + 1AB3D8563AB12635250A6A6E /* StaticLocationScreenCoordinator.swift in Sources */, + DFD5AA8688A34C72D48AF3B1 /* StaticLocationScreenViewModel.swift in Sources */, + 5C164551F7D26E24F09083D3 /* StaticLocationScreenViewModelProtocol.swift in Sources */, + C58E305C380D3ADDF7912180 /* StickerRoomTimelineItem.swift in Sources */, + 197441F1EF23A5DABACCA79F /* StickerRoomTimelineView.swift in Sources */, + 2F94054F50E312AF30BE07F3 /* String.swift in Sources */, + 7640A4B412CACF15D143CCD4 /* Strings+SAS.swift in Sources */, + A7D48E44D485B143AADDB77D /* Strings+Untranslated.swift in Sources */, + 066A1E9B94723EE9F3038044 /* Strings.swift in Sources */, + FF34BF2AF731340AF9414A18 /* SwipeRightAction.swift in Sources */, + 3B98049F56025726FB646ABD /* SwipeToReplyView.swift in Sources */, + E290C78E7F09F47FD2662986 /* Task.swift in Sources */, + 1555A7643D85187D4851040C /* TemplateScreen.swift in Sources */, + 47305C0911C9E1AA774A4000 /* TemplateScreenCoordinator.swift in Sources */, + CCBEC2100CAF2EEBE9DB4156 /* TemplateScreenModels.swift in Sources */, + 275EDE8849A2AC1D9309ED7C /* TemplateScreenViewModel.swift in Sources */, + 2C4C750D0039AFABDF24236C /* TemplateScreenViewModelProtocol.swift in Sources */, + 642DF13C49ED4121C148230E /* TestablePreview.swift in Sources */, + 887AC93C523AEFB640EA5EC8 /* TextBasedRoomTimelineItem.swift in Sources */, + 4FE688FE9375B2FBF424146A /* TextBasedRoomTimelineViewProtocol.swift in Sources */, + BB784A02BADB03C820617A46 /* TextRoomTimelineItem.swift in Sources */, + 53F1196F9C69512306A2693F /* TextRoomTimelineItemContent.swift in Sources */, + D8CFA0EE46376F9FF04EEE45 /* TextRoomTimelineView.swift in Sources */, + 71643093F87153F633A1B025 /* ThreadDecorator.swift in Sources */, + 2AED12987603157C32C2114D /* TimelineBubbleLayout.swift in Sources */, + 798BF3072137833FBD3F4C96 /* TimelineDeliveryStatusView.swift in Sources */, + 109AEB7D33C4497727AFB87F /* TimelineInteractionHandler.swift in Sources */, + E6FA87F773424B27614B23E9 /* TimelineItemAccessibilityModifier.swift in Sources */, + 79959F8E45C3749997482A7F /* TimelineItemBubbledStylerView.swift in Sources */, + A808DC3F72D15C6C5A52317E /* TimelineItemDebugView.swift in Sources */, + C0B97FFEC0083F3A36609E61 /* TimelineItemMacContextMenu.swift in Sources */, + 6C98153D60FF9B648C166C27 /* TimelineItemMenu.swift in Sources */, + AE07F215EBC2B9CBF17AA54B /* TimelineItemMenuAction.swift in Sources */, + 12CD8B5CC30A05061228BF9E /* TimelineItemMenuActionProvider.swift in Sources */, + 1C815DD79B401DEBA2914773 /* TimelineItemMock.swift in Sources */, + 440123E29E2F9B001A775BBE /* TimelineItemProxy.swift in Sources */, + 9586E90A447C4896C0CA3A8E /* TimelineItemReplyDetails.swift in Sources */, + F3ECA377FF77E81A4F1FA062 /* TimelineItemSendInfoLabel.swift in Sources */, + 1B88BB631F7FC45A213BB554 /* TimelineItemSender.swift in Sources */, + EFBBD44C0A16F017C32D2099 /* TimelineItemStatusView.swift in Sources */, + 562EFB9AB62B38830D9AA778 /* TimelineMediaFrame.swift in Sources */, + B818580464CFB5400A3EF6AE /* TimelineModels.swift in Sources */, + E82E13CC3EB923CCB8F8273C /* TimelineProxy.swift in Sources */, + 2FEC6652055984389CE1BBEC /* TimelineProxyProtocol.swift in Sources */, + 8446C2A7ECEFDA79F622725F /* TimelineReactionsView.swift in Sources */, + 4DAEE2468669848B6C9F55B4 /* TimelineReadReceiptsView.swift in Sources */, + 6EB46C92ECFEAE71959D91D2 /* TimelineReplyView.swift in Sources */, + 9FBE1FB20171012260A32492 /* TimelineSenderAvatarView.swift in Sources */, + C4FE0E11A907C8999F92D5A8 /* TimelineStartRoomTimelineItem.swift in Sources */, + 785613C0C092B532198EB3BB /* TimelineStartRoomTimelineView.swift in Sources */, + F2D5C0E1351DA7BD16867629 /* TimelineStyle.swift in Sources */, + 7A0D335D38ECA095A575B4F7 /* TimelineStyler.swift in Sources */, + 6583A95947E78767736CB51A /* TimelineTableViewController.swift in Sources */, + 67EFF46180B939CBF389AECD /* TimelineView.swift in Sources */, + 98EE4259A4A49BC757BA442C /* TimelineViewModel.swift in Sources */, + F8B2F5CBCF2A0E0798E8D646 /* TimelineViewModelProtocol.swift in Sources */, + E37044401D9951D6C02C0855 /* TracingConfiguration.swift in Sources */, + 298F9EC30E918F12AB7F1EE8 /* TypingIndicatorView.swift in Sources */, + 36AC963F2F04069B7FF1AA0C /* UIConstants.swift in Sources */, + A37EED79941AD3B7140B3822 /* UIDevice.swift in Sources */, + 0EE5EBA18BA1FE10254BB489 /* UIFont+AttributedStringBuilder.m in Sources */, + E96005321849DBD7C72A28F2 /* UITestsAppCoordinator.swift in Sources */, + 384D6B9A7DFD7260139D6852 /* UITestsNotificationCenter.swift in Sources */, + 22882C710BC99EC34A5024A0 /* UITestsScreenIdentifier.swift in Sources */, + 706289B086B0A6B0C211763F /* UITestsSignalling.swift in Sources */, + 9603EEF6DE980BB1D15D4707 /* UIView.swift in Sources */, + D02AA6208C7ACB9BE6332394 /* UNNotificationContent.swift in Sources */, + 071A017E415AD378F2961B11 /* URL.swift in Sources */, + 6FD8053301C5FEFA82D2F246 /* URLComponents.swift in Sources */, + 90733645AE76FB33DAD28C2B /* URLSession.swift in Sources */, + 18867F4F1C8991EEC56EA932 /* UTType.swift in Sources */, + 84226AD2E1F1FBC965F3B09E /* UnitTestsAppCoordinator.swift in Sources */, + 34C752A73717C691582DC6C7 /* UnsupportedRoomTimelineItem.swift in Sources */, + D8459AAD6969B1431ECBE990 /* UnsupportedRoomTimelineView.swift in Sources */, + 7A71AEF419904209BB8C2833 /* UserAgentBuilder.swift in Sources */, + 7D58B4F46CAA9A7C3E4C6A30 /* UserDetailsEditScreen.swift in Sources */, + A64B52D9F73F9A6B95AF24FE /* UserDetailsEditScreenCoordinator.swift in Sources */, + 3982C505960006B341CFD0C6 /* UserDetailsEditScreenModels.swift in Sources */, + 4BB51476A29E7E27BC14EA22 /* UserDetailsEditScreenViewModel.swift in Sources */, + 0ACAA31FD0399CEEBA3ECC21 /* UserDetailsEditScreenViewModelProtocol.swift in Sources */, + 828EA5009557C2B9DCD4CA0F /* UserDiscoverySection.swift in Sources */, + 044DD8F80231BC30570F7965 /* UserDiscoveryService.swift in Sources */, + 1C409A26A99F0371C47AFA51 /* UserDiscoveryServiceProtocol.swift in Sources */, + 988BA75A182738150894A23F /* UserIndicator.swift in Sources */, + C4E0D03DF88242697545A9B7 /* UserIndicatorController.swift in Sources */, + 3467FEE8210D301FF1B77001 /* UserIndicatorControllerMock.swift in Sources */, + E3E1E255DC8CB34BD8573E0D /* UserIndicatorControllerProtocol.swift in Sources */, + A14A9419105A1CD42F0511C4 /* UserIndicatorModalView.swift in Sources */, + 9E838A62918E47BC72D6640D /* UserIndicatorPresenter.swift in Sources */, + F7BC744FFA7FE248FAE7F570 /* UserIndicatorToastView.swift in Sources */, + E3291AD16D7A5CB14781819C /* UserNotificationCenterProtocol.swift in Sources */, + 40B79D20A873620F7F128A2C /* UserPreference.swift in Sources */, + 80DEA2A4B20F9E279EAE6B2B /* UserProfile+Mock.swift in Sources */, + ED90A59F068FD0CA27E602ED /* UserProfileListRow.swift in Sources */, + E21FE4C5B614F311C0955859 /* UserProfileProxy.swift in Sources */, + 1A3B073568D1DC8F76F1F3A0 /* UserProfileScreen.swift in Sources */, + 6AEB650311F694A5702255C9 /* UserProfileScreenCoordinator.swift in Sources */, + D4CB979EB4FE26AAD9F9A72B /* UserProfileScreenModels.swift in Sources */, + AC1DB27A4134470846BE49F6 /* UserProfileScreenViewModel.swift in Sources */, + 46A183C6125A669AEB005699 /* UserProfileScreenViewModelProtocol.swift in Sources */, + 69A9B430397C15075D86193F /* UserPropertiesExt.swift in Sources */, + 8AB8ED1051216546CB35FA0E /* UserSession.swift in Sources */, + 4A618590DEB72C4F186BFED4 /* UserSessionFlowCoordinator.swift in Sources */, + 3113065AABBC14CEAE6843FA /* UserSessionFlowCoordinatorStateMachine.swift in Sources */, + 6586E1F1D5F0651D0638FFAF /* UserSessionMock.swift in Sources */, + 978BB24F2A5D31EE59EEC249 /* UserSessionProtocol.swift in Sources */, + 7E91BAC17963ED41208F489B /* UserSessionStore.swift in Sources */, + AC69B6DF15FC451AB2945036 /* UserSessionStoreProtocol.swift in Sources */, + F07D88421A9BC4D03D4A5055 /* VideoRoomTimelineItem.swift in Sources */, + 1A83DD22F3E6F76B13B6E2F9 /* VideoRoomTimelineItemContent.swift in Sources */, + 2CA61BB208CD82EBDB58CD13 /* VideoRoomTimelineView.swift in Sources */, + 6FC10A00D268FCD48B631E37 /* ViewFrameReader.swift in Sources */, + 1318721F4E5F307586D98112 /* VoiceMessageButton.swift in Sources */, + 4681820102DAC8BA586357D4 /* VoiceMessageCache.swift in Sources */, + 4F2DF6138E87A4B8C2488CA3 /* VoiceMessageCacheProtocol.swift in Sources */, + 386720B603F87D156DB01FB2 /* VoiceMessageMediaManager.swift in Sources */, + 9DE801D278AC34737467F937 /* VoiceMessageMediaManagerProtocol.swift in Sources */, + F7932A3F075B0D3F24DEECB5 /* VoiceMessagePreviewComposer.swift in Sources */, + C2879369106A419A5071F1F8 /* VoiceMessageRecorder.swift in Sources */, + 19DED23340D0855B59693ED2 /* VoiceMessageRecorderProtocol.swift in Sources */, + C405528EB4BBEA93579050EE /* VoiceMessageRecordingButton.swift in Sources */, + E0C167D41A48EDB30B447DE3 /* VoiceMessageRecordingComposer.swift in Sources */, + 756EA0D663261889EF64E6D4 /* VoiceMessageRecordingView.swift in Sources */, + A9482B967FC85DA611514D35 /* VoiceMessageRoomPlaybackView.swift in Sources */, + 024E70451A7CD9E4E034D8A9 /* VoiceMessageRoomTimelineItem.swift in Sources */, + 87B4E59A4467F8EC75F82372 /* VoiceMessageRoomTimelineView.swift in Sources */, + CA12AE0DCD57D49CD96C699A /* WaveformCursorView.swift in Sources */, + 63CDC201A5980F304F6D0A1C /* WaveformInteractionModifier.swift in Sources */, + B773ACD8881DB18E876D950C /* WaveformSource.swift in Sources */, + 38CC67C7673FA97C21CCD5B5 /* WebRegistrationScreen.swift in Sources */, + A20364EE08D902E647C11FB3 /* WebRegistrationScreenCoordinator.swift in Sources */, + F0C2C49D707839F5273BFC6D /* WebRegistrationScreenModels.swift in Sources */, + 9FC820C410ED733CE6FC6616 /* WebRegistrationScreenViewModel.swift in Sources */, + 66357ECB73B1290E5490A012 /* WebRegistrationScreenViewModelProtocol.swift in Sources */, + 08CB4BD12CEEDE6AAE4A18DD /* WindowManager.swift in Sources */, + AE5AAD9E32511544FDFA5560 /* WindowManagerProtocol.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BAD5CD7BE53A7C832569B67A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 795A854F63301DC6B46217B9 /* AccessibilityIdentifiers.swift in Sources */, + 44DA28B1E1F9C97C5795F7B3 /* AppLockSetupUITests.swift in Sources */, + BAC845780F17CCFBC5A9CA37 /* AppLockUITests.swift in Sources */, + 7405B4824D45BA7C3D943E76 /* Application.swift in Sources */, + 2A864BB12A8501B47805D828 /* AuthenticationFlowCoordinatorUITests.swift in Sources */, + 7756C4E90CABE6F14F7920A0 /* BugReportUITests.swift in Sources */, + 94D0F36A87E596A93C0C178A /* Bundle.swift in Sources */, + 9F19096BFA629C0AC282B1E4 /* CreateRoomScreenUITests.swift in Sources */, + 5C8AFBF168A41E20835F3B86 /* LoginScreenUITests.swift in Sources */, + 0CF81807BE5FBFC9E2BBCECF /* PollFormScreenUITests.swift in Sources */, + 44121202B4A260C98BF615A7 /* RoomMembersListScreenUITests.swift in Sources */, + D29E046C1E3045E0346C479D /* RoomRolesAndPermissionsUITests.swift in Sources */, + 2F1CF90A3460C153154427F0 /* RoomScreenUITests.swift in Sources */, + 77FACC29F98FE2E65BBB6A5F /* ServerSelectionUITests.swift in Sources */, + 05EC896A4B9AF4A56670C0BB /* SessionVerificationUITests.swift in Sources */, + CBA9EDF305036039166E76FF /* StartChatScreenUITests.swift in Sources */, + C4180F418235DAD9DD173951 /* TemplateScreenUITests.swift in Sources */, + 54AE8860D668AFD96E7E177B /* UITestsScreenIdentifier.swift in Sources */, + 84EFCB95F9DA2979C8042B26 /* UITestsSignalling.swift in Sources */, + B22D857D1E8FCA6DD74A58E3 /* UserSessionScreenTests.swift in Sources */, + 588411C8FD72B2A2DFE5F7DE /* XCUIElement.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D831C59C840FB7B2C1C028A0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DC08ADC41E792086A340A8B3 /* AccessibilityIdentifiers.swift in Sources */, + 1702981A8085BE4FB0EC001B /* Application.swift in Sources */, + 388D39ED9FE1122EA6D76BF2 /* Common.swift in Sources */, + A439B456D0761D6541745CC3 /* NSRegularExpresion.swift in Sources */, + 88356DE7F2AD243AB10C7B7A /* Signposter.swift in Sources */, + 290FDB0FFDC2F1DDF660343E /* TestMeasurementParser.swift in Sources */, + 32B7891D937377A59606EDFC /* UserFlowTests.swift in Sources */, + B444F9C184A377C1B481F07F /* XCUIElement.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 0EEC1557A40FBA6DF49D83A2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C0FAEB81CFD9776CD78CE489 /* ElementX */; + targetProxy = 4D8DD8FE84794CA168A8499A /* PBXContainerItemProxy */; + }; + 2C29670603B37E38705D5FF1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FEB53A5BC378C913769656D8 /* NSE */; + targetProxy = AE0C21E7E01A23610E54DF9D /* PBXContainerItemProxy */; + }; + 421359F1BC0A1816DD34A2BB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C0FAEB81CFD9776CD78CE489 /* ElementX */; + targetProxy = 4448BD77D7203616C4FAD26A /* PBXContainerItemProxy */; + }; + 468963EFD503D7DFAD238754 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C0FAEB81CFD9776CD78CE489 /* ElementX */; + targetProxy = 6848AF4480814C5F810FB7EB /* PBXContainerItemProxy */; + }; + 8E24DC048A099AAFEE13B4F5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C0FAEB81CFD9776CD78CE489 /* ElementX */; + targetProxy = 889C131F86E6415074D382B9 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 135FC689EA39AE1D34153B58 /* SAS.strings */ = { + isa = PBXVariantGroup; + children = ( + 9F40FB0A43DAECEC27C73722 /* bg */, + 2E11E7C396ED06A154CF6DF3 /* cs */, + DA3D82522494E78746B2214E /* de */, + 7447C0AD7EF302CD027D6230 /* en */, + 6722709BD6178E10B70C9641 /* es */, + F3C7252B3461D06175D975A4 /* et */, + CEE20623EB4A9B88FB29F2BA /* fr */, + D196116D2DD3F2757D45FCB7 /* hu */, + 330AF4D121C3396F7A14B21D /* id */, + 61B33F23681660E940BA57F4 /* it */, + 2DA3DBE1A42EAFF93889FA04 /* nl */, + BEE365C5A4E90ACBE398EFFE /* pt */, + FABAC5C4373B0EC24D399663 /* pt-BR */, + 105429F29096729EDD3152CF /* ru */, + A02D1A490944BF01A37586E1 /* sk */, + 7509AB72755DCC4B4E721B36 /* sv */, + AFEF489B8E2450E2BA1A314E /* uk */, + 3AD253E7EFF88F308D644272 /* zh-Hans */, + ); + name = SAS.strings; + sourceTree = ""; + }; + 187853A7E643995EE49FAD43 /* Localizable.stringsdict */ = { + isa = PBXVariantGroup; + children = ( + 34E0FA38BD473FFA6F1AB7A5 /* be */, + 2CF9FE7E0CF9F40D1509E63A /* bg */, + 6654859746B0BE9611459391 /* cs */, + AE5DDBEBBA17973ED4638823 /* de */, + 28EA8BE9EEDBD17555141C7E /* el */, + 13802897C7AFA360EA74C0B0 /* en */, + AACE9B8E1A4AE79A7E2914F6 /* es */, + 4F5F0662483ED69791D63B16 /* et */, + 653610CB5F9776EAAAB98155 /* fr */, + C95ADE8D9527523572532219 /* hu */, + 475D47D0BFE961B02BAC5D49 /* id */, + 6FC5015B9634698BDB8701AF /* it */, + D1896F6288D80E1F3EFB3DF8 /* ka */, + 2AE83A3DD63BCFBB956FE5CB /* nl */, + 4C8D988E82A8DFA13BE46F7C /* pl */, + 8166F121C79C7B62BF01D508 /* pt */, + 21BA866267F84BF4350B0CB7 /* pt-BR */, + E9D059BFE329BE09B6D96A9F /* ro */, + E5F2B6443D1ED8602F328539 /* ru */, + 667DD3A9D932D7D9EB380CAA /* sk */, + 0EE9EAF0309A2A1D67D8FAF5 /* sv */, + 5F12E996BFBEB43815189ABF /* uk */, + DFFB0E7C6D8E190AFA0176DC /* uz */, + AB26D5444A4A7E095222DE8B /* zh-Hans */, + 49E6066092ED45E36BB306F7 /* zh-Hant-TW */, + ); + name = Localizable.stringsdict; + sourceTree = ""; + }; + 7109E709A7738E6BCC4553E6 /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + F0205C03F98BE861EDABCB0D /* be */, + 49193CB0C248D621A96FB2AA /* bg */, + 8D8169443E5AC5FF71BFB3DB /* cs */, + 35AFCF4C05DEED04E3DB1A16 /* de */, + 113356152C099951A6D17D85 /* el */, + CACA846B3E3E9A521D98B178 /* en */, + CBBCC6E74774E79B599625D0 /* es */, + A443FAE2EE820A5790C35C8D /* et */, + CC680E0E79D818706CB28CF8 /* fr */, + 624244C398804ADC885239AA /* hu */, + EF98A02DED04075F7CF0C721 /* id */, + 7B04BD3874D736127A8156B8 /* it */, + 4629710C0337ADD9C8909542 /* ka */, + CDE3F3911FF7CC639BDE5844 /* nl */, + 8140010A796DB2C7977B6643 /* pl */, + 0CB569EAA5017B5B23970655 /* pt */, + 8A9AE4967817E9608E22EB44 /* pt-BR */, + 33E49C5C6F802B4D94CA78D1 /* ro */, + E8294DB9E95C0C0630418466 /* ru */, + AD378D580A41E42560C60E9C /* sk */, + ACA11F7F50A4A3887A18CA5A /* sv */, + ADCB8A232D3A8FB3E16A7303 /* uk */, + 475EB595D7527E9A8A14043E /* uz */, + 284FEEB0789B8894E52A7F34 /* zh-Hans */, + 91CF6F7D08228D16BA69B63B /* zh-Hant-TW */, + ); + name = Localizable.strings; + sourceTree = ""; + }; + 91DE43B8815918E590912DDA /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 34ED3AB7E0287552A5648AB3 /* be */, + EA880E78AF4BD24E45A7808C /* bg */, + 8D1FA20DAB853C1156054912 /* cs */, + 84311D707B09854D67F78BBF /* de */, + 8585C636A10B8141A7AE909F /* el */, + 1215A4FC53D2319E81AE8970 /* en */, + 2525D78FEA7E7B132ED85C58 /* es */, + 2C39D91A31409775B0F4268F /* et */, + ACD7BD6BEE21264F6677904A /* fr */, + 1D652E78832289CD9EB64488 /* hu */, + 7199693797B66245EF97BCF5 /* id */, + 44C314C00533E2C297796B60 /* it */, + E60757AFE04391B43EA568B8 /* nl */, + 997BF045585AF6DB2EBC5755 /* pl */, + A8DF55467ED4CE76B7AE9A33 /* pt */, + 419957D7B1C983D7B3B93678 /* pt-BR */, + 86C8CE2630F54D5FE1591786 /* ro */, + 9B7D8D3638864B7482E148CC /* ru */, + 7D39AF1F659923D77778511E /* sk */, + 969694F67E844FCA51F7E051 /* sv */, + D66B5D86A9AB95E0E01BED82 /* uk */, + FF720BA68256297680980481 /* zh-Hans */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + D2F7194F440375338F8E2487 /* Untranslated.strings */ = { + isa = PBXVariantGroup; + children = ( + AA19C32BD97F45847724E09A /* en */, + ); + name = Untranslated.strings; + sourceTree = ""; + }; + F75DF9500D69A3AAF8339E69 /* Untranslated.stringsdict */ = { + isa = PBXVariantGroup; + children = ( + E0FCA0957FAA0E15A9F5579D /* en */, + ); + name = Untranslated.stringsdict; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 4CB921EC997F763064B8E436 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = NSE/SupportingFiles/NSE.entitlements; + CURRENT_PROJECT_VERSION = "$(CURRENT_PROJECT_VERSION)"; + DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)"; + INFOPLIST_FILE = NSE/SupportingFiles/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = "$(MARKETING_VERSION)"; + OTHER_SWIFT_FLAGS = ( + "-DIS_NSE", + ); + PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse"; + PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; + PRODUCT_NAME = NSE; + SDKROOT = iphoneos; + SWIFT_OBJC_INTERFACE_HEADER_NAME = "GeneratedInterface-Swift.h"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 5206AC013E4214ADC89F8C3C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = PreviewTests/SupportingFiles/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.preview.tests"; + PRODUCT_NAME = PreviewTests; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ElementX.app/ElementX"; + }; + name = Debug; + }; + 584E20C1DA5831E0694FE350 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + 62E1B7866DF0ED442C39A83B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E65DA46BD5CA83747AE144F3 /* secrets.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = ElementX/SupportingFiles/ElementX.entitlements; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CURRENT_PROJECT_VERSION = "$(CURRENT_PROJECT_VERSION)"; + DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)"; + INFOPLIST_FILE = ElementX/SupportingFiles/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = "$(MARKETING_VERSION)"; + OTHER_SWIFT_FLAGS = ( + "-DIS_MAIN_APP", + ); + PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills"; + PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)"; + PRODUCT_NAME = "$(APP_NAME)"; + SDKROOT = iphoneos; + SWIFT_OBJC_BRIDGING_HEADER = "ElementX/SupportingFiles/ElementX-Bridging-Header.h"; + SWIFT_OBJC_INTERFACE_HEADER_NAME = "GeneratedInterface-Swift.h"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 6897D5BC19A2EA6ABD57DE7E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E65DA46BD5CA83747AE144F3 /* secrets.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = ElementX/SupportingFiles/ElementX.entitlements; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CURRENT_PROJECT_VERSION = "$(CURRENT_PROJECT_VERSION)"; + DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)"; + INFOPLIST_FILE = ElementX/SupportingFiles/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = "$(MARKETING_VERSION)"; + OTHER_SWIFT_FLAGS = ( + "-DIS_MAIN_APP", + ); + PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills"; + PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)"; + PRODUCT_NAME = "$(APP_NAME)"; + SDKROOT = iphoneos; + SWIFT_OBJC_BRIDGING_HEADER = "ElementX/SupportingFiles/ElementX-Bridging-Header.h"; + SWIFT_OBJC_INTERFACE_HEADER_NAME = "GeneratedInterface-Swift.h"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 6EE786F14472D5CCF8DD0980 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = UnitTests/SupportingFiles/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.unit.tests"; + PRODUCT_NAME = UnitTests; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ElementX.app/ElementX"; + }; + name = Debug; + }; + 7A90A3EBE1ABAB9EAE0952F0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + APP_DISPLAY_NAME = "Element X"; + APP_GROUP_IDENTIFIER = "group.$(BASE_APP_GROUP_IDENTIFIER)"; + APP_NAME = ElementX; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "colors/accent-color"; + BASE_APP_GROUP_IDENTIFIER = io.element; + BASE_BUNDLE_IDENTIFIER = io.element.elementx; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 7J4U792NQT; + ENABLE_BITCODE = NO; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.4; + KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)"; + MACOSX_DEPLOYMENT_TARGET = 13.3; + MARKETING_VERSION = 1.8.4; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCTION_APP_NAME = Element; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SUPPORTS_MACCATALYST = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 7B3CFB954614306BF6CFFE97 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + APP_DISPLAY_NAME = "Element X"; + APP_GROUP_IDENTIFIER = "group.$(BASE_APP_GROUP_IDENTIFIER)"; + APP_NAME = ElementX; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "colors/accent-color"; + BASE_APP_GROUP_IDENTIFIER = io.element; + BASE_BUNDLE_IDENTIFIER = io.element.elementx; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 7J4U792NQT; + ENABLE_BITCODE = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DEBUG=1", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.4; + KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)"; + MACOSX_DEPLOYMENT_TARGET = 13.3; + MARKETING_VERSION = 1.8.4; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCTION_APP_NAME = Element; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SUPPORTS_MACCATALYST = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 86C938520E216F41879961DF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = UnitTests/SupportingFiles/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.unit.tests"; + PRODUCT_NAME = UnitTests; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ElementX.app/ElementX"; + }; + name = Release; + }; + 933B10FDD7A1E378AB35B76E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = UITests/SupportingFiles/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.ui.tests"; + PRODUCT_NAME = UITests; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = ElementX; + }; + name = Debug; + }; + A1ACA222659F60BAAFB9976B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = UITests/SupportingFiles/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.ui.tests"; + PRODUCT_NAME = UITests; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = ElementX; + }; + name = Release; + }; + A46EFA0820A3F5A3A0C74CFE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = NSE/SupportingFiles/NSE.entitlements; + CURRENT_PROJECT_VERSION = "$(CURRENT_PROJECT_VERSION)"; + DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)"; + INFOPLIST_FILE = NSE/SupportingFiles/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = "$(MARKETING_VERSION)"; + OTHER_SWIFT_FLAGS = ( + "-DIS_NSE", + ); + PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse"; + PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; + PRODUCT_NAME = NSE; + SDKROOT = iphoneos; + SWIFT_OBJC_INTERFACE_HEADER_NAME = "GeneratedInterface-Swift.h"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + AAE81BF8DCDB30B237B10C3E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = IntegrationTests/SupportingFiles/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.integration.tests"; + PRODUCT_NAME = IntegrationTests; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = ElementX; + }; + name = Debug; + }; + D31A0743D3A01F7671ABD26E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; + F0A74453D306F668178A859E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = IntegrationTests/SupportingFiles/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.integration.tests"; + PRODUCT_NAME = IntegrationTests; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = ElementX; + }; + name = Release; + }; + FA443F049643C8C3F0066E59 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = PreviewTests/SupportingFiles/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.preview.tests"; + PRODUCT_NAME = PreviewTests; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ElementX.app/ElementX"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 79663128986C62EFAC289176 /* Build configuration list for PBXNativeTarget "UnitTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6EE786F14472D5CCF8DD0980 /* Debug */, + 86C938520E216F41879961DF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 7AE41FCCF9D1352E2770D1F9 /* Build configuration list for PBXProject "ElementX" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B3CFB954614306BF6CFFE97 /* Debug */, + 7A90A3EBE1ABAB9EAE0952F0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + B15427F8699AD5A5FC75C17E /* Build configuration list for PBXNativeTarget "ElementX" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6897D5BC19A2EA6ABD57DE7E /* Debug */, + 62E1B7866DF0ED442C39A83B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + B7DCEF0CC298791B0EC4CA84 /* Build configuration list for PBXNativeTarget "IntegrationTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AAE81BF8DCDB30B237B10C3E /* Debug */, + F0A74453D306F668178A859E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + C0090A197E33AEC1E7CD03FD /* Build configuration list for PBXAggregateTarget "Periphery" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 584E20C1DA5831E0694FE350 /* Debug */, + D31A0743D3A01F7671ABD26E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + CBD61DB8FBC472BAA66A0CBD /* Build configuration list for PBXNativeTarget "NSE" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A46EFA0820A3F5A3A0C74CFE /* Debug */, + 4CB921EC997F763064B8E436 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + DA320DCEE4CFFAF3A564D280 /* Build configuration list for PBXNativeTarget "PreviewTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5206AC013E4214ADC89F8C3C /* Debug */, + FA443F049643C8C3F0066E59 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + F1B67CF63C1231AEB14D70E6 /* Build configuration list for PBXNativeTarget "UITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 933B10FDD7A1E378AB35B76E /* Debug */, + A1ACA222659F60BAAFB9976B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; +/* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 0CBF57301AA172C21F76CE86 /* XCRemoteSwiftPackageReference "maplibre-gl-native-distribution" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/maplibre/maplibre-gl-native-distribution"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 5.13.0; + }; + }; + 395DE6AE429B7ACC7C7FE31D /* XCRemoteSwiftPackageReference "KZFileWatchers" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/krzysztofzablocki/KZFileWatchers"; + requirement = { + branch = master; + kind = branch; + }; + }; + 44FA555384AD79668D886043 /* XCRemoteSwiftPackageReference "matrix-rich-text-editor-swift" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/matrix-org/matrix-rich-text-editor-swift"; + requirement = { + kind = exactVersion; + version = 2.37.7; + }; + }; + 4BDA7F6042968E8422470F3F /* XCRemoteSwiftPackageReference "LoremSwiftum" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/lukaskubanek/LoremSwiftum"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 2.2.1; + }; + }; + 4C34425923978C97409A3EF2 /* XCRemoteSwiftPackageReference "DSWaveformImage" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/dmrschmidt/DSWaveformImage"; + requirement = { + kind = exactVersion; + version = 14.1.1; + }; + }; + 61916C63E3F5BD900F08DA0C /* XCRemoteSwiftPackageReference "KeychainAccess" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/kishikawakatsumi/KeychainAccess"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 4.2.0; + }; + }; + 6582B5AF3F104B0F7E031E7D /* XCRemoteSwiftPackageReference "SwiftState" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/ReactKit/SwiftState"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 6.0.0; + }; + }; + 6FC4820D8D4559CEECA064D7 /* XCRemoteSwiftPackageReference "matrix-rust-components-swift" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift"; + requirement = { + kind = exactVersion; + version = 1.0.52; + }; + }; + 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/nicklockwood/GZIP"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 1.3.0; + }; + }; + 821C67C9A7F8CC3FD41B28B4 /* XCRemoteSwiftPackageReference "emojibase-bindings" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/matrix-org/emojibase-bindings"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 1.0.0; + }; + }; + 96495DD8554E2F39D3954354 /* XCRemoteSwiftPackageReference "posthog-ios" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/PostHog/posthog-ios"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 3.2.5; + }; + }; + A08925A9D5E3770DEB9D8509 /* XCRemoteSwiftPackageReference "sentry-cocoa" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/getsentry/sentry-cocoa"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 8.30.0; + }; + }; + AC3475112CA40C2C6E78D1EB /* XCRemoteSwiftPackageReference "matrix-analytics-events" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/matrix-org/matrix-analytics-events"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 0.25.0; + }; + }; + C13F55E4518415CB4C278E73 /* XCRemoteSwiftPackageReference "DTCoreText" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/Cocoanetics/DTCoreText"; + requirement = { + kind = exactVersion; + version = 1.6.26; + }; + }; + CCD235515AFCEE6D2005B705 /* XCRemoteSwiftPackageReference "LRUCache" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/nicklockwood/LRUCache"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 1.0.4; + }; + }; + D283517192CAC3E2E6920765 /* XCRemoteSwiftPackageReference "Kingfisher" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/onevcat/Kingfisher"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 7.6.0; + }; + }; + D5F7D47BBAAE0CF1DDEB3034 /* XCRemoteSwiftPackageReference "DeviceKit" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/devicekit/DeviceKit"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 5.2.2; + }; + }; + E025F19D013D9BA6C58B37F4 /* XCRemoteSwiftPackageReference "swift-algorithms" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/apple/swift-algorithms"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 1.0.0; + }; + }; + E2F3DA35D462724CCC61DE2C /* XCRemoteSwiftPackageReference "swift-ogg" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/element-hq/swift-ogg"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 0.0.3; + }; + }; + E9C4F3A12AA1F65C13A8C8EB /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/pointfreeco/swift-snapshot-testing"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 1.17.5; + }; + }; + EC6D0C817B1C21D9D096505A /* XCRemoteSwiftPackageReference "Version" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/mxcl/Version"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 2.0.0; + }; + }; + F71C70A4404CC6D9C4AF35F2 /* XCRemoteSwiftPackageReference "compound-ios" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/element-hq/compound-ios"; + requirement = { + kind = revision; + revision = 92110afc158ac6ee7c68d5e975144bafa6c58396; + }; + }; + F76A08D0EA29A07A54F4EB4D /* XCRemoteSwiftPackageReference "swift-collections" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/apple/swift-collections"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 1.0.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 020597E28A4BC8E1BE8EDF6E /* KeychainAccess */ = { + isa = XCSwiftPackageProductDependency; + package = 61916C63E3F5BD900F08DA0C /* XCRemoteSwiftPackageReference "KeychainAccess" */; + productName = KeychainAccess; + }; + 07FEEEDB11543A7DED420F04 /* Compound */ = { + isa = XCSwiftPackageProductDependency; + package = F71C70A4404CC6D9C4AF35F2 /* XCRemoteSwiftPackageReference "compound-ios" */; + productName = Compound; + }; + 0DD568A494247444A4B56031 /* Kingfisher */ = { + isa = XCSwiftPackageProductDependency; + package = D283517192CAC3E2E6920765 /* XCRemoteSwiftPackageReference "Kingfisher" */; + productName = Kingfisher; + }; + 1081D3630AAD3ACEDDEC3A98 /* LRUCache */ = { + isa = XCSwiftPackageProductDependency; + package = CCD235515AFCEE6D2005B705 /* XCRemoteSwiftPackageReference "LRUCache" */; + productName = LRUCache; + }; + 19CD5B074D7DD44AF4C58BB6 /* SwiftState */ = { + isa = XCSwiftPackageProductDependency; + package = 6582B5AF3F104B0F7E031E7D /* XCRemoteSwiftPackageReference "SwiftState" */; + productName = SwiftState; + }; + 1A6B622CCFDEFB92D9CF1CA5 /* LoremSwiftum */ = { + isa = XCSwiftPackageProductDependency; + package = 4BDA7F6042968E8422470F3F /* XCRemoteSwiftPackageReference "LoremSwiftum" */; + productName = LoremSwiftum; + }; + 1BCD21310B997A6837B854D6 /* GZIP */ = { + isa = XCSwiftPackageProductDependency; + package = 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */; + productName = GZIP; + }; + 21C83087604B154AA30E9A8F /* SnapshotTesting */ = { + isa = XCSwiftPackageProductDependency; + package = E9C4F3A12AA1F65C13A8C8EB /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */; + productName = SnapshotTesting; + }; + 290FDEDA4D764B9F7EBE55A9 /* Algorithms */ = { + isa = XCSwiftPackageProductDependency; + package = E025F19D013D9BA6C58B37F4 /* XCRemoteSwiftPackageReference "swift-algorithms" */; + productName = Algorithms; + }; + 2A3F7BCCB18C15B30CCA39A9 /* AnalyticsEvents */ = { + isa = XCSwiftPackageProductDependency; + package = AC3475112CA40C2C6E78D1EB /* XCRemoteSwiftPackageReference "matrix-analytics-events" */; + productName = AnalyticsEvents; + }; + 2A4106A0A96DC4C273128AA5 /* DSWaveformImageViews */ = { + isa = XCSwiftPackageProductDependency; + package = 4C34425923978C97409A3EF2 /* XCRemoteSwiftPackageReference "DSWaveformImage" */; + productName = DSWaveformImageViews; + }; + 2B43F2AF7456567FE37270A7 /* KeychainAccess */ = { + isa = XCSwiftPackageProductDependency; + package = 61916C63E3F5BD900F08DA0C /* XCRemoteSwiftPackageReference "KeychainAccess" */; + productName = KeychainAccess; + }; + 2B788C81F6369D164ADEB917 /* GZIP */ = { + isa = XCSwiftPackageProductDependency; + package = 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */; + productName = GZIP; + }; + 2B9ACE4FCACB5A8812154424 /* Version */ = { + isa = XCSwiftPackageProductDependency; + package = EC6D0C817B1C21D9D096505A /* XCRemoteSwiftPackageReference "Version" */; + productName = Version; + }; + 36B7FC232711031AA2B0D188 /* DTCoreText */ = { + isa = XCSwiftPackageProductDependency; + package = C13F55E4518415CB4C278E73 /* XCRemoteSwiftPackageReference "DTCoreText" */; + productName = DTCoreText; + }; + 3853B78FB8531B83936C5DA6 /* SwiftState */ = { + isa = XCSwiftPackageProductDependency; + package = 6582B5AF3F104B0F7E031E7D /* XCRemoteSwiftPackageReference "SwiftState" */; + productName = SwiftState; + }; + 385D4C28F9DC5CF53BD9ECDB /* DeviceKit */ = { + isa = XCSwiftPackageProductDependency; + package = D5F7D47BBAAE0CF1DDEB3034 /* XCRemoteSwiftPackageReference "DeviceKit" */; + productName = DeviceKit; + }; + 391D11F92DFC91666AA1503F /* SwiftOGG */ = { + isa = XCSwiftPackageProductDependency; + package = E2F3DA35D462724CCC61DE2C /* XCRemoteSwiftPackageReference "swift-ogg" */; + productName = SwiftOGG; + }; + 3FE40E79C36E7903121E6E3B /* SwiftOGG */ = { + isa = XCSwiftPackageProductDependency; + package = E2F3DA35D462724CCC61DE2C /* XCRemoteSwiftPackageReference "swift-ogg" */; + productName = SwiftOGG; + }; + 4003BC24B24C9E63D3304177 /* DeviceKit */ = { + isa = XCSwiftPackageProductDependency; + package = D5F7D47BBAAE0CF1DDEB3034 /* XCRemoteSwiftPackageReference "DeviceKit" */; + productName = DeviceKit; + }; + 4278261E147DB2DE5CFB7FC5 /* PostHog */ = { + isa = XCSwiftPackageProductDependency; + package = 96495DD8554E2F39D3954354 /* XCRemoteSwiftPackageReference "posthog-ios" */; + productName = PostHog; + }; + 50009897F60FAE7D63EF5E5B /* Kingfisher */ = { + isa = XCSwiftPackageProductDependency; + package = D283517192CAC3E2E6920765 /* XCRemoteSwiftPackageReference "Kingfisher" */; + productName = Kingfisher; + }; + 527578916BD388A09F5A8036 /* DTCoreText */ = { + isa = XCSwiftPackageProductDependency; + package = C13F55E4518415CB4C278E73 /* XCRemoteSwiftPackageReference "DTCoreText" */; + productName = DTCoreText; + }; + 531CE4334AC5CA8DFF6AEB84 /* DTCoreText */ = { + isa = XCSwiftPackageProductDependency; + package = C13F55E4518415CB4C278E73 /* XCRemoteSwiftPackageReference "DTCoreText" */; + productName = DTCoreText; + }; + 593FBBF394712F2963E98A0B /* DTCoreText */ = { + isa = XCSwiftPackageProductDependency; + package = C13F55E4518415CB4C278E73 /* XCRemoteSwiftPackageReference "DTCoreText" */; + productName = DTCoreText; + }; + 6647C55D93508C7CE9D954A5 /* MatrixRustSDK */ = { + isa = XCSwiftPackageProductDependency; + package = 6FC4820D8D4559CEECA064D7 /* XCRemoteSwiftPackageReference "matrix-rust-components-swift" */; + productName = MatrixRustSDK; + }; + 67E7A6F388D3BF85767609D9 /* Sentry */ = { + isa = XCSwiftPackageProductDependency; + package = A08925A9D5E3770DEB9D8509 /* XCRemoteSwiftPackageReference "sentry-cocoa" */; + productName = Sentry; + }; + 75361A9D8A3C5501EADB225D /* SentrySwiftUI */ = { + isa = XCSwiftPackageProductDependency; + package = A08925A9D5E3770DEB9D8509 /* XCRemoteSwiftPackageReference "sentry-cocoa" */; + productName = SentrySwiftUI; + }; + 7731767AE437BA3BD2CC14A8 /* Sentry */ = { + isa = XCSwiftPackageProductDependency; + package = A08925A9D5E3770DEB9D8509 /* XCRemoteSwiftPackageReference "sentry-cocoa" */; + productName = Sentry; + }; + 78A5A8DE1E2B09C978C7F3B0 /* KeychainAccess */ = { + isa = XCSwiftPackageProductDependency; + package = 61916C63E3F5BD900F08DA0C /* XCRemoteSwiftPackageReference "KeychainAccess" */; + productName = KeychainAccess; + }; + 78B28D75FF7AF8E6146DEE2A /* LRUCache */ = { + isa = XCSwiftPackageProductDependency; + package = CCD235515AFCEE6D2005B705 /* XCRemoteSwiftPackageReference "LRUCache" */; + productName = LRUCache; + }; + 7B6BC3219ADD8AA0311D2B86 /* SnapshotTesting */ = { + isa = XCSwiftPackageProductDependency; + package = E9C4F3A12AA1F65C13A8C8EB /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */; + productName = SnapshotTesting; + }; + 800631D7250B7F93195035F1 /* KeychainAccess */ = { + isa = XCSwiftPackageProductDependency; + package = 61916C63E3F5BD900F08DA0C /* XCRemoteSwiftPackageReference "KeychainAccess" */; + productName = KeychainAccess; + }; + 81DB3AB6CE996AB3954F4F03 /* KZFileWatchers */ = { + isa = XCSwiftPackageProductDependency; + package = 395DE6AE429B7ACC7C7FE31D /* XCRemoteSwiftPackageReference "KZFileWatchers" */; + productName = KZFileWatchers; + }; + 886A0A498FA01E8EDD451D05 /* Sentry */ = { + isa = XCSwiftPackageProductDependency; + package = A08925A9D5E3770DEB9D8509 /* XCRemoteSwiftPackageReference "sentry-cocoa" */; + productName = Sentry; + }; + 940C605265DD82DA0C655E23 /* Kingfisher */ = { + isa = XCSwiftPackageProductDependency; + package = D283517192CAC3E2E6920765 /* XCRemoteSwiftPackageReference "Kingfisher" */; + productName = Kingfisher; + }; + 9573B94B1C86C6DF751AF3FD /* SwiftState */ = { + isa = XCSwiftPackageProductDependency; + package = 6582B5AF3F104B0F7E031E7D /* XCRemoteSwiftPackageReference "SwiftState" */; + productName = SwiftState; + }; + 997C7385E1A07E061D7E2100 /* GZIP */ = { + isa = XCSwiftPackageProductDependency; + package = 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */; + productName = GZIP; + }; + 9C73F37731C9FDED1BB24C1C /* Collections */ = { + isa = XCSwiftPackageProductDependency; + package = F76A08D0EA29A07A54F4EB4D /* XCRemoteSwiftPackageReference "swift-collections" */; + productName = Collections; + }; + A05AF81DDD14AD58CB0E1B9B /* Version */ = { + isa = XCSwiftPackageProductDependency; + package = EC6D0C817B1C21D9D096505A /* XCRemoteSwiftPackageReference "Version" */; + productName = Version; + }; + A20EA00CCB9DBE0FFB17DD09 /* Collections */ = { + isa = XCSwiftPackageProductDependency; + package = F76A08D0EA29A07A54F4EB4D /* XCRemoteSwiftPackageReference "swift-collections" */; + productName = Collections; + }; + A2AE110B053B55E38F8D10C7 /* KZFileWatchers */ = { + isa = XCSwiftPackageProductDependency; + package = 395DE6AE429B7ACC7C7FE31D /* XCRemoteSwiftPackageReference "KZFileWatchers" */; + productName = KZFileWatchers; + }; + A678E40E917620059695F067 /* MatrixRustSDK */ = { + isa = XCSwiftPackageProductDependency; + package = 6FC4820D8D4559CEECA064D7 /* XCRemoteSwiftPackageReference "matrix-rust-components-swift" */; + productName = MatrixRustSDK; + }; + A7CA6F33C553805035C3B114 /* DeviceKit */ = { + isa = XCSwiftPackageProductDependency; + package = D5F7D47BBAAE0CF1DDEB3034 /* XCRemoteSwiftPackageReference "DeviceKit" */; + productName = DeviceKit; + }; + AD544C0FA48DFFB080920061 /* Collections */ = { + isa = XCSwiftPackageProductDependency; + package = F76A08D0EA29A07A54F4EB4D /* XCRemoteSwiftPackageReference "swift-collections" */; + productName = Collections; + }; + B1E8B697DF78FE7F61FC6CA4 /* MatrixRustSDK */ = { + isa = XCSwiftPackageProductDependency; + package = 6FC4820D8D4559CEECA064D7 /* XCRemoteSwiftPackageReference "matrix-rust-components-swift" */; + productName = MatrixRustSDK; + }; + BA93CD75CCE486660C9040BD /* Collections */ = { + isa = XCSwiftPackageProductDependency; + package = F76A08D0EA29A07A54F4EB4D /* XCRemoteSwiftPackageReference "swift-collections" */; + productName = Collections; + }; + BC01130651CB23340B899032 /* DeviceKit */ = { + isa = XCSwiftPackageProductDependency; + package = D5F7D47BBAAE0CF1DDEB3034 /* XCRemoteSwiftPackageReference "DeviceKit" */; + productName = DeviceKit; + }; + C05729B1684C331F5FFE9232 /* Emojibase */ = { + isa = XCSwiftPackageProductDependency; + package = 821C67C9A7F8CC3FD41B28B4 /* XCRemoteSwiftPackageReference "emojibase-bindings" */; + productName = Emojibase; + }; + C1BF15833233CD3BDB7E2B1D /* Mapbox */ = { + isa = XCSwiftPackageProductDependency; + package = 0CBF57301AA172C21F76CE86 /* XCRemoteSwiftPackageReference "maplibre-gl-native-distribution" */; + productName = Mapbox; + }; + C2C69B8BA5A9702E7A8BC08F /* MatrixRustSDK */ = { + isa = XCSwiftPackageProductDependency; + package = 6FC4820D8D4559CEECA064D7 /* XCRemoteSwiftPackageReference "matrix-rust-components-swift" */; + productName = MatrixRustSDK; + }; + CA07D57389DACE18AEB6A5E2 /* WysiwygComposer */ = { + isa = XCSwiftPackageProductDependency; + package = 44FA555384AD79668D886043 /* XCRemoteSwiftPackageReference "matrix-rich-text-editor-swift" */; + productName = WysiwygComposer; + }; + CCE5BF78B125320CBF3BB834 /* PostHog */ = { + isa = XCSwiftPackageProductDependency; + package = 96495DD8554E2F39D3954354 /* XCRemoteSwiftPackageReference "posthog-ios" */; + productName = PostHog; + }; + D661CAB418C075A94306A792 /* AnalyticsEvents */ = { + isa = XCSwiftPackageProductDependency; + package = AC3475112CA40C2C6E78D1EB /* XCRemoteSwiftPackageReference "matrix-analytics-events" */; + productName = AnalyticsEvents; + }; + DCA3C4A997AD28E6918D4CE5 /* Compound */ = { + isa = XCSwiftPackageProductDependency; + package = F71C70A4404CC6D9C4AF35F2 /* XCRemoteSwiftPackageReference "compound-ios" */; + productName = Compound; + }; + DE8DC9B3FBA402117DC4C49F /* Kingfisher */ = { + isa = XCSwiftPackageProductDependency; + package = D283517192CAC3E2E6920765 /* XCRemoteSwiftPackageReference "Kingfisher" */; + productName = Kingfisher; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = AC22997D58D612146053154D /* Project object */; +} diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000000..aedc0764c2 --- /dev/null +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,293 @@ +{ + "originHash" : "52385e2a478cc9455693d0b93dc33b988ac1d4742acceeaee288944dff8b78e0", + "pins" : [ + { + "identity" : "compound-design-tokens", + "kind" : "remoteSourceControl", + "location" : "https://github.com/element-hq/compound-design-tokens", + "state" : { + "revision" : "2af7bb571eb30cbfbd67cdda6617500507ef46aa", + "version" : "1.8.0" + } + }, + { + "identity" : "compound-ios", + "kind" : "remoteSourceControl", + "location" : "https://github.com/element-hq/compound-ios", + "state" : { + "revision" : "92110afc158ac6ee7c68d5e975144bafa6c58396" + } + }, + { + "identity" : "devicekit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/devicekit/DeviceKit", + "state" : { + "revision" : "fe41d18eccd92a115cffaa35dfff03018c67e635", + "version" : "5.2.2" + } + }, + { + "identity" : "dswaveformimage", + "kind" : "remoteSourceControl", + "location" : "https://github.com/dmrschmidt/DSWaveformImage", + "state" : { + "revision" : "6074c2334a5a34afaa8394df853c8ceb026ad137", + "version" : "14.1.1" + } + }, + { + "identity" : "dtcoretext", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Cocoanetics/DTCoreText", + "state" : { + "revision" : "b664664825da565b4c2b7a17dbe2369f68ae43d9", + "version" : "1.6.26" + } + }, + { + "identity" : "dtfoundation", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Cocoanetics/DTFoundation.git", + "state" : { + "revision" : "76062513434421cb6c8a1ae1d4f8368a7ebc2da3", + "version" : "1.7.18" + } + }, + { + "identity" : "emojibase-bindings", + "kind" : "remoteSourceControl", + "location" : "https://github.com/matrix-org/emojibase-bindings", + "state" : { + "revision" : "6ca06fefac9329fece851a2a4df7979b1699970a", + "version" : "1.0.5" + } + }, + { + "identity" : "gzip", + "kind" : "remoteSourceControl", + "location" : "https://github.com/nicklockwood/GZIP", + "state" : { + "revision" : "bd55f1d89e71ae3f481da74cd4adeadbb849620c", + "version" : "1.3.1" + } + }, + { + "identity" : "keychainaccess", + "kind" : "remoteSourceControl", + "location" : "https://github.com/kishikawakatsumi/KeychainAccess", + "state" : { + "revision" : "84e546727d66f1adc5439debad16270d0fdd04e7", + "version" : "4.2.2" + } + }, + { + "identity" : "kingfisher", + "kind" : "remoteSourceControl", + "location" : "https://github.com/onevcat/Kingfisher", + "state" : { + "revision" : "af4be924ad984cf4d16f4ae4df424e79a443d435", + "version" : "7.6.2" + } + }, + { + "identity" : "kzfilewatchers", + "kind" : "remoteSourceControl", + "location" : "https://github.com/krzysztofzablocki/KZFileWatchers", + "state" : { + "branch" : "master", + "revision" : "d27a9557427d261adccdf4b566acc9d9c0fec6f4" + } + }, + { + "identity" : "loremswiftum", + "kind" : "remoteSourceControl", + "location" : "https://github.com/lukaskubanek/LoremSwiftum", + "state" : { + "revision" : "8942e732e50458cde5dccf9996afa16f29372853", + "version" : "2.2.2" + } + }, + { + "identity" : "lrucache", + "kind" : "remoteSourceControl", + "location" : "https://github.com/nicklockwood/LRUCache", + "state" : { + "revision" : "6d2b5246c9c98dcd498552bb22f08d55b12a8371", + "version" : "1.0.4" + } + }, + { + "identity" : "maplibre-gl-native-distribution", + "kind" : "remoteSourceControl", + "location" : "https://github.com/maplibre/maplibre-gl-native-distribution", + "state" : { + "revision" : "ffda61e298c1490d4860d5184e80d618aaadc089", + "version" : "5.13.0" + } + }, + { + "identity" : "matrix-analytics-events", + "kind" : "remoteSourceControl", + "location" : "https://github.com/matrix-org/matrix-analytics-events", + "state" : { + "revision" : "c9b40120a5f7b8ce1bab3f09f8417fdc9407f006", + "version" : "0.25.0" + } + }, + { + "identity" : "matrix-rich-text-editor-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/matrix-org/matrix-rich-text-editor-swift", + "state" : { + "revision" : "30909decc48be8e06c93eacffa4ec71b539888a9", + "version" : "2.37.7" + } + }, + { + "identity" : "matrix-rust-components-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/element-hq/matrix-rust-components-swift", + "state" : { + "revision" : "11c6d99d62035b02f4c448daebff4d63c962da20", + "version" : "1.0.52" + } + }, + { + "identity" : "ogg-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/vector-im/ogg-swift.git", + "state" : { + "revision" : "9d82ed838404f10b607a1a1689f404563e9115c3", + "version" : "0.8.3" + } + }, + { + "identity" : "opus-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/vector-im/opus-swift", + "state" : { + "revision" : "11f1887767cbc87c4b64b789ee830b779cc744cb", + "version" : "0.8.4" + } + }, + { + "identity" : "posthog-ios", + "kind" : "remoteSourceControl", + "location" : "https://github.com/PostHog/posthog-ios", + "state" : { + "revision" : "8b2508444962d67aa5f8770074f32d493383dafd", + "version" : "3.2.5" + } + }, + { + "identity" : "prefire", + "kind" : "remoteSourceControl", + "location" : "https://github.com/BarredEwe/Prefire", + "state" : { + "revision" : "0b7b6e6fe98af7e12b1440ca8fe81b3033ecf873", + "version" : "2.9.0" + } + }, + { + "identity" : "sentry-cocoa", + "kind" : "remoteSourceControl", + "location" : "https://github.com/getsentry/sentry-cocoa", + "state" : { + "revision" : "8fd4e804f2e72e0b9c1b189ce4e8349c4d10b6a2", + "version" : "8.30.0" + } + }, + { + "identity" : "sfsafesymbols", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SFSafeSymbols/SFSafeSymbols", + "state" : { + "revision" : "e2e28f4e56e1769c2ec3c61c9355fc64eb7a535a", + "version" : "5.3.0" + } + }, + { + "identity" : "swift-algorithms", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-algorithms", + "state" : { + "revision" : "b14b7f4c528c942f121c8b860b9410b2bf57825e", + "version" : "1.0.0" + } + }, + { + "identity" : "swift-collections", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-collections", + "state" : { + "revision" : "a902f1823a7ff3c9ab2fba0f992396b948eda307", + "version" : "1.0.5" + } + }, + { + "identity" : "swift-numerics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-numerics", + "state" : { + "revision" : "0a5bc04095a675662cf24757cc0640aa2204253b", + "version" : "1.0.2" + } + }, + { + "identity" : "swift-ogg", + "kind" : "remoteSourceControl", + "location" : "https://github.com/element-hq/swift-ogg", + "state" : { + "revision" : "d60d4dd3eaaa3b07eafed76420ea03b79a516a13", + "version" : "0.0.3" + } + }, + { + "identity" : "swift-snapshot-testing", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-snapshot-testing", + "state" : { + "revision" : "7b0bbbae90c41f848f90ac7b4df6c4f50068256d", + "version" : "1.17.5" + } + }, + { + "identity" : "swift-syntax", + "kind" : "remoteSourceControl", + "location" : "https://github.com/swiftlang/swift-syntax", + "state" : { + "revision" : "74203046135342e4a4a627476dd6caf8b28fe11b", + "version" : "509.0.0" + } + }, + { + "identity" : "swiftstate", + "kind" : "remoteSourceControl", + "location" : "https://github.com/ReactKit/SwiftState", + "state" : { + "revision" : "887e75b96da6be36a062e1b0ef832c32a803348b", + "version" : "6.0.1" + } + }, + { + "identity" : "swiftui-introspect", + "kind" : "remoteSourceControl", + "location" : "https://github.com/siteline/SwiftUI-Introspect", + "state" : { + "revision" : "807f73ce09a9b9723f12385e592b4e0aaebd3336", + "version" : "1.3.0" + } + }, + { + "identity" : "version", + "kind" : "remoteSourceControl", + "location" : "https://github.com/mxcl/Version", + "state" : { + "revision" : "1fe824b80d89201652e7eca7c9252269a1d85e25", + "version" : "2.0.1" + } + } + ], + "version" : 3 +} diff --git a/ElementX/Resources/Localizations/be.lproj/Localizable.strings b/ElementX/Resources/Localizations/be.lproj/Localizable.strings index ef91271ab2..299b8b732a 100644 --- a/ElementX/Resources/Localizations/be.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/be.lproj/Localizable.strings @@ -27,17 +27,20 @@ "action_back" = "ะะฐะทะฐะด"; "action_call" = "ะ—ะฒะฐะฝะพะบ"; "action_cancel" = "ะกะบะฐัะฐะฒะฐั†ัŒ"; +"action_cancel_for_now" = "ะะดะผัะฝั–ั†ัŒ ะฟะฐะบัƒะปัŒ"; "action_choose_photo" = "ะ’ั‹ะฑั€ะฐั†ัŒ ั„ะพั‚ะฐ"; "action_clear" = "ะั‡ั‹ัั†ั–ั†ัŒ"; "action_close" = "ะ—ะฐะบั€ั‹ั†ัŒ"; "action_complete_verification" = "ะŸั€ะฐะฒะตั€ะบะฐ ะทะฐะฒะตั€ัˆะฐะฝะฐ"; "action_confirm" = "ะŸะฐั†ะฒะตั€ะดะทั–ั†ัŒ"; +"action_confirm_password" = "Confirm password"; "action_continue" = "ะŸั€ะฐั†ัะณะฝัƒั†ัŒ"; "action_copy" = "ะšะฐะฟั–ั€ะฐะฒะฐั†ัŒ"; "action_copy_link" = "ะกะบะฐะฟั–ั€ะฐะฒะฐั†ัŒ ัะฟะฐัั‹ะปะบัƒ"; "action_copy_link_to_message" = "ะกะบะฐะฟั–ั€ะฐะฒะฐั†ัŒ ัะฟะฐัั‹ะปะบัƒ ะฝะฐ ะฟะฐะฒะตะดะฐะผะปะตะฝะฝะต"; "action_create" = "ะกั‚ะฒะฐั€ั‹ั†ัŒ"; "action_create_a_room" = "ะกั‚ะฒะฐั€ั‹ั†ะต ะฟะฐะบะพะน"; +"action_deactivate" = "Deactivate"; "action_decline" = "ะะดั…ั–ะปั–ั†ัŒ"; "action_delete_poll" = "ะ’ั‹ะดะฐะปั–ั†ัŒ ะฐะฟั‹ั‚ะฐะฝะฝะต"; "action_disable" = "ะะดะบะปัŽั‡ั‹ั†ัŒ"; @@ -70,6 +73,7 @@ "action_ok" = "ะ”ะพะฑั€ะฐ"; "action_open_settings" = "ะะฐะปะฐะดั‹"; "action_open_with" = "ะะดะบั€ั‹ั†ัŒ ะท ะดะฐะฟะฐะผะพะณะฐะน"; +"action_pin" = "ะ—ะฐะผะฐั†ะฐะฒะฐั†ัŒ"; "action_quick_reply" = "ะฅัƒั‚ะบั– ะฐะดะบะฐะท"; "action_quote" = "ะฆั‹ั‚ะฐั‚ะฐ"; "action_react" = "ะ ัะฐะบั†ั‹ั"; @@ -80,6 +84,7 @@ "action_report_bug" = "ะŸะฐะฒะตะดะฐะผั–ั†ัŒ ะฟั€ะฐ ะฟะฐะผั‹ะปะบัƒ"; "action_report_content" = "ะŸะฐัะบะฐั€ะดะทั–ั†ั†ะฐ ะฝะฐ ะทะผะตัั‚"; "action_reset" = "ะกะบั–ะฝัƒั†ัŒ"; +"action_reset_identity" = "ะกะบั–ะฝัƒั†ัŒ ั–ะดัะฝั‚ั‹ั„ั–ะบะฐั†ั‹ะนะฝั‹ั ะดะฐะดะทะตะฝั‹ั"; "action_retry" = "ะŸะฐัžั‚ะฐั€ั‹ั†ัŒ"; "action_retry_decryption" = "ะŸะฐัžั‚ะฐั€ั‹ั†ัŒ ั€ะฐััˆั‹ั„ั€ะพัžะบัƒ"; "action_save" = "ะ—ะฐั…ะฐะฒะฐั†ัŒ"; @@ -99,10 +104,18 @@ "action_take_photo" = "ะ—ั€ะฐะฑั–ั†ัŒ ั„ะพั‚ะฐ"; "action_tap_for_options" = "ะ”ะฐะบั€ะฐะฝั–ั†ะตัั, ะบะฐะฑ ัƒะฑะฐั‡ั‹ั†ัŒ ะฟะฐั€ะฐะผะตั‚ั€ั‹"; "action_try_again" = "ะŸะฐัžั‚ะฐั€ั‹ั†ัŒ ัะฟั€ะพะฑัƒ"; +"action_unpin" = "ะะดะผะฐั†ะฐะฒะฐั†ัŒ"; +"action_view_in_timeline" = "ะŸั€ะฐะณะปัะด ัƒ ั…ั€ะพะฝั–ั†ั‹"; "action_view_source" = "ะŸั€ะฐะณะปัะด ะทั‹ั…ะพะดะฝะฐะณะฐ ะบะพะดะฐ"; "action_yes" = "ะขะฐะบ"; "action.load_more" = "ะ—ะฐะณั€ัƒะทั–ั†ัŒ ะฑะพะปัŒัˆ"; -"action.pin" = "ะ—ะฐะผะฐั†ะฐะฒะฐั†ัŒ"; +"action_deactivate_account" = "Deactivate account"; +"banner_migrate_to_native_sliding_sync_action" = "ะ’ั‹ะนัั†ั– ั– ะฐะฑะฝะฐะฒั–ั†ัŒ"; +"banner_migrate_to_native_sliding_sync_description" = "Your server now supports a new, faster protocol. Log out and log back in to upgrade now. Doing this now will help you avoid a forced logout when the old protocol is removed later."; +"banner_migrate_to_native_sliding_sync_force_logout_title" = "Your homeserver no longer supports the old protocol. Please log out and log back in to continue using the app."; +"banner_migrate_to_native_sliding_sync_title" = "Upgrade available"; +"banner.set_up_recovery.content" = "Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices."; +"banner.set_up_recovery.title" = "ะะฐะปะฐะดะทั–ั†ัŒ ะฐะดะฝะฐัžะปะตะฝะฝะต"; "common_about" = "ะะฑ ะฟั€ะฐะณั€ะฐะผะต"; "common_acceptable_use_policy" = "ะŸะฐะปั–ั‚ั‹ะบะฐ ะดะฐะฟัƒัˆั‡ะฐะปัŒะฝะฐะณะฐ ะฒั‹ะบะฐั€ั‹ัั‚ะฐะฝะฝั"; "common_advanced_settings" = "ะŸะฐัˆั‹ั€ะฐะฝั‹ั ะฝะฐะปะฐะดั‹"; @@ -214,6 +227,7 @@ "common_waiting_for_decryption_key" = "ะงะฐะบะฐัŽ ะณัั‚ะฐ ะฟะฐะฒะตะดะฐะผะปะตะฝะฝะต"; "common.do_not_show_this_again" = "ะะต ะฟะฐะบะฐะทะฒะฐั†ัŒ ะณัั‚ะฐ ะทะฝะพัž"; "common.open_source_licenses" = "ะ›ั–ั†ัะฝะทั–ั– ะท ะฐะดะบั€ั‹ั‚ั‹ะผ ะทั‹ั…ะพะดะฝั‹ะผ ะบะพะดะฐะผ"; +"common.pinned" = "ะ—ะฐะผะฐั†ะฐะฒะฐะฝั‹"; "common.send_to" = "ะะดะฟั€ะฐะฒั–ั†ัŒ"; "common_no_room_name" = "ะัะผะฐ ะฝะฐะทะฒั‹ ะฟะฐะบะพั"; "common_poll_end_confirmation" = "ะ’ั‹ ัžะฟััžะฝะตะฝั‹, ัˆั‚ะพ ั…ะพั‡ะฐั†ะต ัะบะพะฝั‡ั‹ั†ัŒ ะณัั‚ะฐะต ะฐะฟั‹ั‚ะฐะฝะฝะต?"; @@ -244,6 +258,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_failed_creating_the_permalink" = "ะะต ะฐั‚ั€ั‹ะผะฐะปะฐัั ัั‚ะฒะฐั€ั‹ั†ัŒ ะฟะฐัั‚ะฐัะฝะฝัƒัŽ ัะฟะฐัั‹ะปะบัƒ"; "error_failed_loading_map" = "%1$@ ะฝะต ะฐั‚ั€ั‹ะผะฐะปะฐัั ะทะฐะณั€ัƒะทั–ั†ัŒ ะบะฐั€ั‚ัƒ. ะšะฐะปั– ะปะฐัะบะฐ ะฟะฐัะฟั€ะฐะฑัƒะนั†ะต ะทะฝะพัž ะฟะฐะทะฝะตะน."; "error_failed_loading_messages" = "ะะต ัžะดะฐะปะพัั ะทะฐะณั€ัƒะทั–ั†ัŒ ะฟะฐะฒะตะดะฐะผะปะตะฝะฝั–"; @@ -254,6 +269,8 @@ "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" = "ะะต ะทะฐัˆั‹ั„ั€ะฐะฒะฐะฝั‹."; "event_shield_reason_unknown_device" = "ะ—ะฐัˆั‹ั„ั€ะฐะฒะฐะฝะฐ ะฝะตะฒัะดะพะผะฐะน ั†ั– ะฒั‹ะดะฐะปะตะฝะฐะน ะฟั€ั‹ะปะฐะดะฐะน."; "event_shield_reason_unsigned_device" = "ะ—ะฐัˆั‹ั„ั€ะฐะฒะฐะฝะฐ ะฟั€ั‹ะปะฐะดะฐะน, ะฝะต ะฟะฐั†ะฒะตั€ะดะถะฐะฝะฐะน ัะต ัžะปะฐะดะฐะปัŒะฝั–ะบะฐะผ."; "event_shield_reason_unverified_identity" = "ะ—ะฐัˆั‹ั„ั€ะฐะฒะฐะฝะฐ ะฝะตะฟั€ะฐะฒะตั€ะฐะฝั‹ะผ ะบะฐั€ั‹ัั‚ะฐะปัŒะฝั–ะบะฐะผ."; @@ -275,11 +292,14 @@ "notification_inline_reply_failed" = "** ะะต ะฐั‚ั€ั‹ะผะฐะปะฐัั ะดะฐัะปะฐั†ัŒ - ะบะฐะปั– ะปะฐัะบะฐ, ะฐะดะบั€ั‹ะนั†ะต ะฟะฐะบะพะน"; "notification_invitation_action_reject" = "ะะดั…ั–ะปั–ั†ัŒ"; "notification_invite_body" = "ะ—ะฐะฟั€ะฐัั–ัž(-ะปะฐ) ะฒะฐั ัƒ ั‡ะฐั‚"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "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_sender_me" = "ะฏ"; +"notification_sender_mention_reply" = "%1$@ mentioned or replied"; "notification_test_push_notification_content" = "ะ’ั‹ ะฟั€ะฐะณะปัะดะฐะตั†ะต ะฐะฟะฐะฒััˆั‡ัะฝะฝะต! ะะฐั†ั–ัะฝั–ั†ะต ะผัะฝะต!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -312,10 +332,27 @@ "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_pinned_timeline_empty_state_description" = "ะะฐั†ั–ัะฝั–ั†ะต ะฝะฐ ะฟะฐะฒะตะดะฐะผะปะตะฝะฝะต ั– ะฐะฑัั€ั‹ั†ะต ยซ%1$@ ยป, ะบะฐะฑ ัƒะบะปัŽั‡ั‹ั†ัŒ ััŽะดั‹."; +"screen_pinned_timeline_empty_state_headline" = "ะ—ะฐะผะฐั†ัƒะตั†ะต ะฒะฐะถะฝั‹ั ะฟะฐะฒะตะดะฐะผะปะตะฝะฝั–, ะบะฐะฑ ั–ั… ะผะพะถะฝะฐ ะฑั‹ะปะพ ะปั‘ะณะบะฐ ะทะฝะฐะนัั†ั–"; +"screen_pinned_timeline_screen_title_empty" = "ะ—ะฐะผะฐั†ะฐะฒะฐะฝั‹ั ะฟะฐะฒะตะดะฐะผะปะตะฝะฝั–"; +"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" = "ะฃัั‘ ั€ะพัžะฝะฐ ะฐะดะฟั€ะฐะฒั–ั†ัŒ ะฟะฐะฒะตะดะฐะผะปะตะฝะฝะต"; +"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.room.pinned_banner_indicator" = "%1$@ of %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ Pinned messages"; -"screen.room.pinned_banner_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_details_pinned_events_row_title" = "ะ—ะฐะผะฐั†ะฐะฒะฐะฝั‹ั ะฟะฐะฒะตะดะฐะผะปะตะฝะฝั–"; +"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_account_provider_change" = "ะ—ะผัะฝั–ั†ัŒ ะฟั€ะฐะฒะฐะนะดะฐั€ะฐ ัžะปั–ะบะพะฒะฐะณะฐ ะทะฐะฟั–ััƒ"; "screen_account_provider_form_hint" = "ะะดั€ะฐั ั…ะฐั‚ะฝัะณะฐ ัะตั€ะฒะตั€ะฐ"; "screen_account_provider_form_notice" = "ะฃะฒัะดะทั–ั†ะต ะฟะพัˆัƒะบะฐะฒั‹ ะทะฐะฟั‹ั‚ ะฐะฑะพ ะฐะดั€ะฐั ะดะฐะผะตะฝะฐ."; @@ -398,6 +435,7 @@ "screen_chat_backup_recovery_action_confirm_description" = "ะ’ะฐัˆะฐ ั€ัะทะตั€ะฒะพะฒะฐั ะบะพะฟั–ั ั‡ะฐั‚ะฐ ะทะฐั€ะฐะท ะฝะต ัั–ะฝั…ั€ะฐะฝั–ะทะฐะฒะฐะฝะฐ."; "screen_chat_backup_recovery_action_setup" = "ะะฐะปะฐะดะทัŒั†ะต ะฐะดะฝะฐัžะปะตะฝะฝะต"; "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$@"; @@ -421,6 +459,17 @@ "screen_create_room_public_option_description" = "ะŸะฐะฒะตะดะฐะผะปะตะฝะฝั– ะฝะต ะทะฐัˆั‹ั„ั€ะฐะฒะฐะฝั‹, ั– ะบะพะถะฝั‹ ะผะพะถะฐ ั–ั… ะฟั€ะฐั‡ั‹ั‚ะฐั†ัŒ. ะ’ั‹ ะผะพะถะฐั†ะต ัžะบะปัŽั‡ั‹ั†ัŒ ัˆั‹ั„ั€ะฐะฒะฐะฝะฝะต ะฟะฐะทะฝะตะน."; "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_edit_poll_delete_confirmation" = "ะ’ั‹ ัžะฟััžะฝะตะฝั‹, ัˆั‚ะพ ั…ะพั‡ะฐั†ะต ะฒั‹ะดะฐะปั–ั†ัŒ ะณัั‚ะฐะต ะฐะฟั‹ั‚ะฐะฝะฝะต?"; "screen_edit_profile_display_name" = "ะ‘ะฐั‡ะฝะฐะต ั–ะผั"; "screen_edit_profile_display_name_placeholder" = "ะ’ะฐัˆะฐ ะฑะฐั‡ะฝะฐะต ั–ะผั"; @@ -428,12 +477,20 @@ "screen_edit_profile_error_title" = "ะะตะผะฐะณั‡ั‹ะผะฐ ะฐะฑะฝะฐะฒั–ั†ัŒ ะฟั€ะพั„ั–ะปัŒ"; "screen_edit_profile_title" = "ะ ัะดะฐะณะฐะฒะฐั†ัŒ ะฟั€ะพั„ั–ะปัŒ"; "screen_edit_profile_updating_details" = "ะะฑะฝะฐัžะปะตะฝะฝะต ะฟั€ะพั„ั–ะปัŽโ€ฆ"; +"screen_encryption_reset_action_continue_reset" = "ะŸั€ะฐั†ัะณะฝัƒั†ัŒ ัะบั–ะด"; +"screen_encryption_reset_bullet_1" = "ะ”ะฐะดะทะตะฝั‹ั ะฒะฐัˆะฐะณะฐ ัžะปั–ะบะพะฒะฐะณะฐ ะทะฐะฟั–ััƒ, ะบะฐะฝั‚ะฐะบั‚ั‹, ะฝะฐะปะฐะดั‹ ั– ัะฟั–ั ั‡ะฐั‚ะฐัž ะฑัƒะดัƒั†ัŒ ะทะฐั…ะฐะฒะฐะฝั‹"; +"screen_encryption_reset_bullet_2" = "ะ’ั‹ ัั‚ั€ะฐั†ั–ั†ะต ั–ัะฝัƒัŽั‡ัƒัŽ ะณั–ัั‚ะพั€ั‹ัŽ ะฟะฐะฒะตะดะฐะผะปะตะฝะฝััž"; +"screen_encryption_reset_bullet_3" = "ะ’ะฐะผ ั‚ั€ัะฑะฐ ะฑัƒะดะทะต ะทะฝะพัž ะทะฐะฟััžะฝั–ั†ัŒ ัžัะต ะฒะฐัˆั‹ ั–ัะฝัƒัŽั‡ั‹ั ะฟั€ั‹ะปะฐะดั‹ ั– ะบะฐะฝั‚ะฐะบั‚ั‹"; +"screen_encryption_reset_footer" = "ะŸั€ะฐั†ัะณะฒะฐะนั†ะต, ั‚ะพะปัŒะบั– ะบะฐะปั– ะฒั‹ ัžะฟััžะฝะตะฝั‹ั, ัˆั‚ะพ ัั‚ั€ะฐั†ั–ะปั– ัžัะต ะฐัั‚ะฐั‚ะฝั–ั ะฟั€ั‹ะปะฐะดั‹ ั– ะบะปัŽั‡ ะฐะดะฝะฐัžะปะตะฝะฝั."; +"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" = "ะ’ั‹ะบะฐั€ั‹ัั‚ะพัžะฒะฐะนั†ะต ั–ะฝัˆัƒัŽ ะฟั€ั‹ะปะฐะดัƒ"; +"screen_identity_confirmation_use_recovery_key" = "ะ’ั‹ะบะฐั€ั‹ัั‚ะพัžะฒะฐั†ัŒ ะบะปัŽั‡ ะฐะดะฝะฐัžะปะตะฝะฝั"; "screen_identity_confirmed_subtitle" = "ะฆัะฟะตั€ ะฒั‹ ะผะพะถะฐั†ะต ะฑััะฟะตั‡ะฝะฐ ั‡ั‹ั‚ะฐั†ัŒ ั– ะฐะดะฟั€ะฐัžะปัั†ัŒ ะฟะฐะฒะตะดะฐะผะปะตะฝะฝั–, ั– ัžัะต, ะท ะบั–ะผ ะฒั‹ ะผะฐะตั†ะต ะทะฝะพัั–ะฝั‹ ัž ั‡ะฐั†ะต, ั‚ะฐะบัะฐะผะฐ ะผะพะณัƒั†ัŒ ะดะฐะฒัั€ะฐั†ัŒ ะณัั‚ะฐะน ะฟั€ั‹ะปะฐะดะทะต."; "screen_identity_confirmed_title" = "ะŸั€ั‹ะปะฐะดะฐ ะฟั€ะฐะฒะตั€ะฐะฝะฐ"; -"screen_identity_use_another_device" = "ะ’ั‹ะบะฐั€ั‹ัั‚ะพัžะฒะฐะนั†ะต ั–ะฝัˆัƒัŽ ะฟั€ั‹ะปะฐะดัƒ"; "screen_identity_waiting_on_other_device" = "ะงะฐะบะฐะฝะฝะต ะฝะฐ ั–ะฝัˆะฐะน ะฟั€ั‹ะปะฐะดะทะต..."; "screen_invites_decline_chat_message" = "ะ’ั‹ ัžะฟััžะฝะตะฝั‹ั, ัˆั‚ะพ ั…ะพั‡ะฐั†ะต ะฐะดั…ั–ะปั–ั†ัŒ ะทะฐะฟั€ะฐัˆัะฝะฝะต ัž %1$@?"; "screen_invites_decline_chat_title" = "ะะดั…ั–ะปั–ั†ัŒ ะทะฐะฟั€ะฐัˆัะฝะฝะต"; @@ -556,7 +613,6 @@ "screen_recovery_key_confirm_error_content" = "ะŸะฐัžั‚ะฐั€ั‹ั†ะต ัะฟั€ะพะฑัƒ, ะบะฐะฑ ะฟะฐั†ะฒะตั€ะดะทั–ั†ัŒ ะดะพัั‚ัƒะฟ ะดะฐ ั€ัะทะตั€ะฒะพะฒะฐะน ะบะพะฟั–ั– ั‡ะฐั‚ะฐ."; "screen_recovery_key_confirm_error_title" = "ะัะฟั€ะฐะฒั–ะปัŒะฝั‹ ะบะปัŽั‡ ะฐะดะฝะฐัžะปะตะฝะฝั"; "screen_recovery_key_confirm_key_description" = "ะšะฐะปั– ัž ะฒะฐั ั‘ัั†ัŒ ะบะปัŽั‡ ะฐะดะฝะฐัžะปะตะฝะฝั ะฐะฑะพ ะฟะฐั€ะพะปัŒะฝะฐั ั„ั€ะฐะทะฐ, ะณัั‚ะฐ ั‚ะฐะบัะฐะผะฐ ะฑัƒะดะทะต ะฟั€ะฐั†ะฐะฒะฐั†ัŒ."; -"screen_recovery_key_confirm_key_label" = "ะšะปัŽั‡ ะฐะดะฝะฐัžะปะตะฝะฝั ะฐะฑะพ ะบะพะด ะดะพัั‚ัƒะฟัƒ"; "screen_recovery_key_confirm_key_placeholder" = "ะฃะฒะตัั†ั–..."; "screen_recovery_key_confirm_lost_recovery_key" = "ะกั‚ั€ะฐั†ั–ะปั– ะบะปัŽั‡ ะฐะดะฝะฐัžะปะตะฝะฝั?"; "screen_recovery_key_confirm_success" = "ะšะปัŽั‡ ะฐะดะฝะฐัžะปะตะฝะฝั ะฟะฐั†ะฒะตั€ะดะถะฐะฝั‹"; @@ -577,6 +633,14 @@ "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_placeholder" = "ะฃะฒะพะด..."; +"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_room_alias_resolver_resolve_alias_failure" = "ะะต ัžะดะฐะปะพัั ั€ะฐะทะฐะฑั€ะฐั†ั†ะฐ ะท ะฟัะตัžะดะฐะฝั–ะผะฐะผ ะฟะฐะบะพั."; "screen_room_attachment_source_camera" = "ะšะฐะผะตั€ะฐ"; "screen_room_attachment_source_camera_video" = "ะ—ะฐะฟั–ัะฐั†ัŒ ะฒั–ะดัะฐ"; @@ -775,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "ะ’ั‹ ะทะฐั…ะฐะฒะฐะปั– ัะฒะพะน ะบะปัŽั‡ ะฐะดะฝะฐัžะปะตะฝะฝั?"; "screen_start_chat_error_starting_chat" = "ะŸั€ั‹ ัะฟั€ะพะฑะต ะฟะฐั‡ะฐั†ัŒ ั‡ะฐั‚ ะฐะดะฑั‹ะปะฐัั ะฟะฐะผั‹ะปะบะฐ"; "screen_view_location_title" = "ะœะตัั†ะฐะทะฝะฐั…ะพะดะถะฐะฝะฝะต"; -"screen_waitlist_message" = "ะ—ะฐั€ะฐะท ั–ัะฝัƒะต ะฒั‹ัะพะบั– ะฟะพะฟั‹ั‚ ะฝะฐ %1$@ ะฝะฐ %2$@. ะšะฐะปั– ะปะฐัะบะฐ, ะฒัั€ะฝั–ั†ะตัั ัž ะฟั€ะฐะณั€ะฐะผัƒ ะฟั€ะฐะท ะฝะตะบะฐะปัŒะบั– ะดะทั‘ะฝ ั– ะฟะฐัะฟั€ะฐะฑัƒะนั†ะต ะทะฝะพัž.\n\nะ”ะทัะบัƒะน ะทะฐ ั†ัั€ะฟะตะฝะฝะต!"; -"screen_waitlist_title" = "ะะผะฐะปัŒ ะณะฐั‚ะพะฒะฐ."; -"screen_waitlist_title_success" = "ะ’ั‹ ะทะฐั€ัะณั–ัั‚ั€ะฐะฒะฐะฝั‹."; "screen_welcome_bullet_1" = "ะ—ะฒะฐะฝะบั–, ะฐะฟั‹ั‚ะฐะฝะฝั–, ะฟะพัˆัƒะบ ั– ะผะฝะพะณะฐะต ั–ะฝัˆะฐะต ะฑัƒะดะทะต ะดะฐะดะฐะดะทะตะฝะฐ ะฟะฐะทะฝะตะน ัƒ ะณัั‚ั‹ะผ ะณะพะดะทะต."; "screen_welcome_bullet_2" = "ะ“ั–ัั‚ะพั€ั‹ั ะฟะฐะฒะตะดะฐะผะปะตะฝะฝััž ะดะปั ะทะฐัˆั‹ั„ั€ะฐะฒะฐะฝั‹ั… ะฟะฐะบะพััž ะฟะฐะบัƒะปัŒ ะฝะตะดะฐัั‚ัƒะฟะฝะฐ."; "screen_welcome_bullet_3" = "ะœั‹ ะฑัƒะดะทะตะผ ั€ะฐะดั‹ ะฟะฐั‡ัƒั†ัŒ ะฒะฐัˆะฐะต ะผะตั€ะบะฐะฒะฐะฝะฝะต, ะฟะฐะฒะตะดะฐะผั–ั†ะต ะฝะฐะผ ะฐะฑ ะณัั‚ั‹ะผ ะฟั€ะฐะท ัั‚ะฐั€ะพะฝะบัƒ ะฝะฐะปะฐะด."; @@ -834,6 +895,12 @@ "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$@ ะทะผัะฝั–ัž(-ะปะฐ) ะทะฐะผะฐั†ะฐะฒะฐะฝั‹ั ะฟะฐะฒะตะดะฐะผะปะตะฝะฝั–"; +"state_event_room_pinned_events_changed_by_you" = "ะ’ั‹ ะทะผัะฝั–ะปั– ะทะฐะผะฐั†ะฐะฒะฐะฝั‹ั ะฟะฐะฒะตะดะฐะผะปะตะฝะฝั–"; +"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_by_you" = "ะ’ั‹ ะฐะดะผะฐั†ะฐะฒะฐะปั– ะฟะฐะฒะตะดะฐะผะปะตะฝะฝะต"; "state_event_room_reject" = "%1$@ ะฐะดั…ั–ะปั–ัž(-ะปะฐ) ะทะฐะฟั€ะฐัˆัะฝะฝะต"; "state_event_room_reject_by_you" = "ะ’ั‹ ะฐะดั…ั–ะปั–ะปั– ะทะฐะฟั€ะฐัˆัะฝะฝะต"; "state_event_room_remove" = "%1$@ ะฒั‹ะดะฐะปั–ัž(-ะปะฐ) %2$@"; @@ -921,6 +988,7 @@ "screen_dm_details_unblock_user" = "ะ ะฐะทะฑะปะฐะบั–ั€ะฐะฒะฐั†ัŒ ะบะฐั€ั‹ัั‚ะฐะปัŒะฝั–ะบะฐ"; "screen_edit_poll_delete_confirmation_title" = "ะ’ั‹ะดะฐะปั–ั†ัŒ ะฐะฟั‹ั‚ะฐะฝะฝะต"; "screen_edit_poll_title" = "ะ ัะดะฐะณะฐะฒะฐั†ัŒ ะฐะฟั‹ั‚ะฐะฝะฝะต"; +"screen_identity_use_another_device" = "ะ’ั‹ะบะฐั€ั‹ัั‚ะพัžะฒะฐะนั†ะต ั–ะฝัˆัƒัŽ ะฟั€ั‹ะปะฐะดัƒ"; "screen_login_subtitle" = "Matrix - ะณัั‚ะฐ ะฐะดะบั€ั‹ั‚ะฐั ัะตั‚ะบะฐ ะดะปั ะฑััะฟะตั‡ะฝะฐะน, ะดัั†ัะฝั‚ั€ะฐะปั–ะทะฐะฒะฐะฝะฐะน ััƒะฒัะทั–."; "screen_qr_code_login_invalid_scan_state_retry_button" = "ะŸะฐัžั‚ะฐั€ั‹ั†ัŒ ัะฟั€ะพะฑัƒ"; "screen_report_content_block_user" = "ะ—ะฐะฑะปะฐะบั–ั€ะฐะฒะฐั†ัŒ ะบะฐั€ั‹ัั‚ะฐะปัŒะฝั–ะบะฐ"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "ะ’ั‹ะนัั†ั–"; "screen_signout_confirmation_dialog_title" = "ะ’ั‹ะนัั†ั–"; "screen_signout_preference_item" = "ะ’ั‹ะนัั†ั–"; -"screen_waitlist_message_success" = "ะ’ั–ั‚ะฐะตะผ ัƒ %1$@!"; diff --git a/ElementX/Resources/Localizations/be.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/be.lproj/Localizable.stringsdict index 3247240639..954044d393 100644 --- a/ElementX/Resources/Localizations/be.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/be.lproj/Localizable.stringsdict @@ -218,6 +218,24 @@ ะัะฟั€ะฐะฒั–ะปัŒะฝั‹ PIN-ะบะพะด. ะฃ ะฒะฐั ะทะฐัั‚ะฐะปะฐัั %1$d ัˆะฐะฝั†ะฐัž + screen_pinned_timeline_screen_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d ะ—ะฐะผะฐั†ะฐะฒะฐะฝะฐะต ะฟะฐะฒะตะดะฐะผะปะตะฝะฝะต + few + %1$d ะ—ะฐะผะฐั†ะฐะฒะฐะฝั‹ั ะฟะฐะฒะตะดะฐะผะปะตะฝะฝั– + many + %1$d ะ—ะฐะผะฐั†ะฐะฒะฐะฝั‹ั… ะฟะฐะฒะตะดะฐะผะปะตะฝะฝััž + + screen_room_member_list_header_title NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/bg.lproj/Localizable.strings b/ElementX/Resources/Localizations/bg.lproj/Localizable.strings index aecb4cdda2..357c221e5b 100644 --- a/ElementX/Resources/Localizations/bg.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/bg.lproj/Localizable.strings @@ -27,17 +27,20 @@ "action_back" = "ะะฐะทะฐะด"; "action_call" = "Call"; "action_cancel" = "ะžั‚ะบะฐะท"; +"action_cancel_for_now" = "Cancel for now"; "action_choose_photo" = "ะ˜ะทะฑะพั€ ะฝะฐ ัะฝะธะผะบะฐ"; "action_clear" = "ะ˜ะทั‡ะธัั‚ะฒะฐะฝะต"; "action_close" = "ะ—ะฐั‚ะฒะฐั€ัะฝะต"; "action_complete_verification" = "ะ—ะฐะฒัŠั€ัˆะฒะฐะฝะต ะฝะฐ ะฟะพั‚ะฒัŠั€ะถะดะฐะฒะฐะฝะตั‚ะพ"; "action_confirm" = "ะŸะพั‚ะฒัŠั€ะถะดะฐะฒะฐะฝะต"; +"action_confirm_password" = "Confirm password"; "action_continue" = "ะŸั€ะพะดัŠะปะถะฐะฒะฐะฝะต"; "action_copy" = "ะšะพะฟะธั€ะฐะฝะต"; "action_copy_link" = "ะšะพะฟะธั€ะฐะฝะต ะฝะฐ ะฒั€ัŠะทะบะฐั‚ะฐ"; "action_copy_link_to_message" = "ะšะพะฟะธั€ะฐะฝะต ะฝะฐ ะฒั€ัŠะทะบะฐั‚ะฐ ะบัŠะผ ััŠะพะฑั‰ะตะฝะธะตั‚ะพ"; "action_create" = "ะกัŠะทะดะฐะฒะฐะฝะต"; "action_create_a_room" = "ะกัŠะทะดะฐะฒะฐะฝะต ะฝะฐ ัั‚ะฐั"; +"action_deactivate" = "Deactivate"; "action_decline" = "ะžั‚ั…ะฒัŠั€ะปัะฝะต"; "action_delete_poll" = "ะ˜ะทั‚ั€ะธะฒะฐะฝะต ะฝะฐ ะฐะฝะบะตั‚ะฐั‚ะฐ"; "action_disable" = "ะ”ะตะฐะบั‚ะธะฒะธั€ะฐะฝะต"; @@ -70,6 +73,7 @@ "action_ok" = "ะ”ะพะฑั€ะต"; "action_open_settings" = "ะะฐัั‚ั€ะพะนะบะธ"; "action_open_with" = "ะžั‚ะฒะฐั€ัะฝะต ั"; +"action_pin" = "Pin"; "action_quick_reply" = "ะ‘ัŠั€ะท ะพั‚ะณะพะฒะพั€"; "action_quote" = "ะฆะธั‚ะฐั‚"; "action_react" = "ะ ะตะฐะบั†ะธั"; @@ -80,6 +84,7 @@ "action_report_bug" = "Report bug"; "action_report_content" = "ะ”ะพะบะปะฐะดะฒะฐะฝะต ะฝะฐ ััŠะดัŠั€ะถะฐะฝะธะตั‚ะพ"; "action_reset" = "Reset"; +"action_reset_identity" = "Reset identity"; "action_retry" = "ะŸะพะฒั‚ะพั€ะตะฝ ะพะฟะธั‚"; "action_retry_decryption" = "ะŸะพะฒั‚ะพั€ะตะฝ ะพะฟะธั‚ ะทะฐ ั€ะฐะทัˆะธั„ั€ะพะฒะฐะฝะต"; "action_save" = "ะ—ะฐะฟะฐะทะฒะฐะฝะต"; @@ -99,10 +104,18 @@ "action_take_photo" = "ะกะฝะธะผะบะฐ"; "action_tap_for_options" = "ะ”ะพะบะพัะฝะตั‚ะต ะทะฐ ะพะฟั†ะธะธ"; "action_try_again" = "ะŸะพะฒั‚ะพั€ะตะฝ ะพะฟะธั‚"; +"action_unpin" = "Unpin"; +"action_view_in_timeline" = "View in timeline"; "action_view_source" = "ะŸั€ะตะณะปะตะด ะฝะฐ ะธะทั‚ะพั‡ะฝะธะบะฐ"; "action_yes" = "ะ”ะฐ"; "action.load_more" = "ะ—ะฐั€ะตะถะดะฐะฝะต ะฝะฐ ะพั‰ะต"; -"action.pin" = "Pin"; +"action_deactivate_account" = "Deactivate account"; +"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" = "Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices."; +"banner.set_up_recovery.title" = "Set up recovery"; "common_about" = "ะžั‚ะฝะพัะฝะพ"; "common_acceptable_use_policy" = "Acceptable use policy"; "common_advanced_settings" = "ะ ะฐะทัˆะธั€ะตะฝะธ ะฝะฐัั‚ั€ะพะนะบะธ"; @@ -214,6 +227,7 @@ "common_waiting_for_decryption_key" = "ะ’ ะพั‡ะฐะบะฒะฐะฝะต ะฝะฐ ั‚ะพะฒะฐ ััŠะพะฑั‰ะตะฝะธะต"; "common.do_not_show_this_again" = "Do not show this again"; "common.open_source_licenses" = "Open source licenses"; +"common.pinned" = "Pinned"; "common.send_to" = "Send to"; "common_no_room_name" = "No room name"; "common_poll_end_confirmation" = "ะกะธะณัƒั€ะฝะธ ะปะธ ัั‚ะต, ั‡ะต ะธัะบะฐั‚ะต ะดะฐ ะฟั€ะธะบะปัŽั‡ะธั‚ะต ั‚ะฐะทะธ ะฐะฝะบะตั‚ะฐ?"; @@ -244,6 +258,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_failed_creating_the_permalink" = "Failed creating the permalink"; "error_failed_loading_map" = "%1$@ could not load the map. Please try again later."; "error_failed_loading_messages" = "Failed loading messages"; @@ -254,6 +269,8 @@ "error_some_messages_have_not_been_sent" = "Some messages have not been sent"; "error_unknown" = "Sorry, an error occurred"; "event_shield_reason_authenticity_not_guaranteed" = "The authenticity of this encrypted message can't be guaranteed on this device."; +"event_shield_reason_previously_verified" = "Encrypted by a previously-verified user."; +"event_shield_reason_sent_in_clear" = "Not encrypted."; "event_shield_reason_unknown_device" = "Encrypted by an unknown or deleted device."; "event_shield_reason_unsigned_device" = "Encrypted by a device not verified by its owner."; "event_shield_reason_unverified_identity" = "Encrypted by an unverified user."; @@ -275,11 +292,14 @@ "notification_inline_reply_failed" = "** ะะตัƒัะฟะตัˆะฝะพ ะธะทะฟั€ะฐั‰ะฐะฝะต - ะผะพะปั, ะพั‚ะฒะพั€ะตั‚ะต ัั‚ะฐัั‚ะฐ"; "notification_invitation_action_reject" = "Reject"; "notification_invite_body" = "Invited you to chat"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "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_sender_me" = "Me"; +"notification_sender_mention_reply" = "%1$@ mentioned or replied"; "notification_test_push_notification_content" = "You are viewing the notification! Click me!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -312,10 +332,27 @@ "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_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_pinned_timeline_screen_title_empty" = "Pinned messages"; +"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" = "Notify the whole room"; -"screen.room.pinned_banner_indicator" = "%1$@ of %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ Pinned messages"; -"screen.room.pinned_banner_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_details_pinned_events_row_title" = "Pinned messages"; +"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_account_provider_change" = "ะŸั€ะพะผัะฝะฐ ะฝะฐ ะดะพัั‚ะฐะฒั‡ะธะบะฐ ะฝะฐ ะฐะบะฐัƒะฝั‚"; "screen_account_provider_form_hint" = "Homeserver address"; "screen_account_provider_form_notice" = "ะ’ัŠะฒะตะดะตั‚ะต ั‚ะตั€ะผะธะฝ ะทะฐ ั‚ัŠั€ัะตะฝะต ะธะปะธ ะฐะดั€ะตั ะฝะฐ ะดะพะผะตะนะฝ."; @@ -398,6 +435,7 @@ "screen_chat_backup_recovery_action_confirm_description" = "ะ ะตะทะตั€ะฒะฝะพั‚ะพ ะบะพะฟะธะต ะฝะฐ ั‡ะฐั‚ะพะฒะตั‚ะต ะฒะธ ะฒ ะผะพะผะตะฝั‚ะฐ ะฝะต ะต ัะธะฝั…ั€ะพะฝะธะทะธั€ะฐะฝะพ."; "screen_chat_backup_recovery_action_setup" = "Set up recovery"; "screen_chat_backup_recovery_action_setup_description" = "Get access to your encrypted messages if you lose all your devices or are signed out of %1$@ everywhere."; +"screen_create_account_title" = "Create account"; "screen_create_new_recovery_key_list_item_1" = "Open %1$@ in a desktop device"; "screen_create_new_recovery_key_list_item_2" = "Sign into your account again"; "screen_create_new_recovery_key_list_item_3" = "When asked to verify your device, select %1$@"; @@ -421,6 +459,17 @@ "screen_create_room_public_option_description" = "ะกัŠะพะฑั‰ะตะฝะธัั‚ะฐ ะฝะต ัะฐ ัˆะธั„ั€ะพะฒะฐะฝะธ ะธ ะฒัะตะบะธ ะผะพะถะต ะดะฐ ะณะธ ะฟั€ะพั‡ะตั‚ะต. ะœะพะถะตั‚ะต ะดะฐ ะฐะบั‚ะธะฒะธั€ะฐั‚ะต ัˆะธั„ั€ะพะฒะฐะฝะตั‚ะพ ะฝะฐ ะฟะพ-ะบัŠัะฝะฐ ะดะฐั‚ะฐ."; "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_edit_poll_delete_confirmation" = "ะกะธะณัƒั€ะฝะธ ะปะธ ัั‚ะต, ั‡ะต ะธัะบะฐั‚ะต ะดะฐ ะธะทั‚ั€ะธะตั‚ะต ั‚ะฐะทะธ ะฐะฝะบะตั‚ะฐ?"; "screen_edit_profile_display_name" = "ะ˜ะผะต"; "screen_edit_profile_display_name_placeholder" = "ะ’ะฐัˆะตั‚ะพ ะ˜ะผะต"; @@ -428,12 +477,20 @@ "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" = "Your account details, contacts, preferences, and chat list will be kept"; +"screen_encryption_reset_bullet_2" = "You will lose your existing message history"; +"screen_encryption_reset_bullet_3" = "You will need to verify all your existing devices and contacts again"; +"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_identity_confirmation_create_new_recovery_key" = "Create a new recovery key"; "screen_identity_confirmation_subtitle" = "Verify this device to set up secure messaging."; -"screen_identity_confirmation_title" = "Confirm that it's you"; +"screen_identity_confirmation_title" = "Confirm your identity"; +"screen_identity_confirmation_use_another_device" = "Use another device"; +"screen_identity_confirmation_use_recovery_key" = "Use recovery key"; "screen_identity_confirmed_subtitle" = "Now you can read or send messages securely, and anyone you chat with can also trust this device."; "screen_identity_confirmed_title" = "Device verified"; -"screen_identity_use_another_device" = "Use another device"; "screen_identity_waiting_on_other_device" = "Waiting on other deviceโ€ฆ"; "screen_invites_decline_chat_message" = "ะกะธะณัƒั€ะฝะธ ะปะธ ัั‚ะต, ั‡ะต ะธัะบะฐั‚ะต ะดะฐ ะพั‚ั…ะฒัŠั€ะปะธั‚ะต ะฟะพะบะฐะฝะฐั‚ะฐ ะทะฐ ะฟั€ะธััŠะตะดะธะฝัะฒะฐะฝะต ะฒ %1$@?"; "screen_invites_decline_chat_title" = "ะžั‚ะบะฐะทะฒะฐะฝะต ะฝะฐ ะฟะพะบะฐะฝะฐ"; @@ -556,7 +613,6 @@ "screen_recovery_key_confirm_error_content" = "Please try again to confirm access to your chat backup."; "screen_recovery_key_confirm_error_title" = "ะะตะฟั€ะฐะฒะธะปะตะฝ ะบะปัŽั‡ ะทะฐ ะฒัŠะทัั‚ะฐะฝะพะฒัะฒะฐะฝะต"; "screen_recovery_key_confirm_key_description" = "ะ’ัŠะฒะตะดะตั‚ะต 48-ัะธะผะฒะพะปะฝะธั ะบะพะด."; -"screen_recovery_key_confirm_key_label" = "Recovery key or passcode"; "screen_recovery_key_confirm_key_placeholder" = "ะ’ัŠะฒะตะดะตั‚ะตโ€ฆ"; "screen_recovery_key_confirm_lost_recovery_key" = "Lost your recovery key?"; "screen_recovery_key_confirm_success" = "ะšะปัŽั‡ัŠั‚ ะทะฐ ะฒัŠะทัั‚ะฐะฝะพะฒัะฒะฐะฝะต ะต ะฟะพั‚ะฒัŠั€ะดะตะฝ"; @@ -577,6 +633,14 @@ "screen_report_content_block_user_hint" = "Check if you want to hide all current and future messages from this user"; "screen_report_content_explanation" = "This message will be reported to your homeserverโ€™s administrator. They will not be able to read any encrypted messages."; "screen_report_content_hint" = "Reason for reporting this content"; +"screen_reset_encryption_confirmation_alert_action" = "Yes, reset now"; +"screen_reset_encryption_confirmation_alert_subtitle" = "This process is irreversible."; +"screen_reset_encryption_confirmation_alert_title" = "Are you sure you want to reset your identity?"; +"screen_reset_encryption_password_placeholder" = "Enterโ€ฆ"; +"screen_reset_encryption_password_subtitle" = "Confirm that you want to reset your identity."; +"screen_reset_encryption_password_title" = "Enter your account password to continue"; +"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_room_alias_resolver_resolve_alias_failure" = "Failed to resolve room alias."; "screen_room_attachment_source_camera" = "ะšะฐะผะตั€ะฐ"; "screen_room_attachment_source_camera_video" = "ะ—ะฐะฟะธั ะฝะฐ ะฒะธะดะตะพ"; @@ -775,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "Have you saved your recovery key?"; "screen_start_chat_error_starting_chat" = "An error occurred when trying to start a chat"; "screen_view_location_title" = "ะœะตัั‚ะพะฟะพะปะพะถะตะฝะธะต"; -"screen_waitlist_message" = "There's a high demand for %1$@ on %2$@ at the moment. Come back to the app in a few days and try again.\n\nThanks for your patience!"; -"screen_waitlist_title" = "Youโ€™re almost there."; -"screen_waitlist_title_success" = "You're in."; "screen_welcome_bullet_1" = "Calls, polls, search and more will be added later this year."; "screen_welcome_bullet_2" = "ะฅั€ะพะฝะพะปะพะณะธัั‚ะฐ ะฝะฐ ััŠะพะฑั‰ะตะฝะธัั‚ะฐ ะทะฐ ัˆะธั„ั€ะพะฒะฐะฝะธ ัั‚ะฐะธ ะฒัะต ะพั‰ะต ะฝะต ะต ะฝะฐะปะธั‡ะฝะฐ."; "screen_welcome_bullet_3" = "Weโ€™d love to hear from you, let us know what you think via the settings page."; @@ -834,6 +895,12 @@ "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$@ changed the pinned messages"; +"state_event_room_pinned_events_changed_by_you" = "You changed the pinned messages"; +"state_event_room_pinned_events_pinned" = "%1$@ pinned a message"; +"state_event_room_pinned_events_pinned_by_you" = "You pinned a message"; +"state_event_room_pinned_events_unpinned" = "%1$@ unpinned a message"; +"state_event_room_pinned_events_unpinned_by_you" = "You unpinned a message"; "state_event_room_reject" = "%1$@ ะพั‚ั…ะฒัŠั€ะปะธ ะฟะพะบะฐะฝะฐั‚ะฐ"; "state_event_room_reject_by_you" = "ะ’ะธะต ะพั‚ั…ะฒัŠั€ะปะธั…ั‚ะต ะฟะพะบะฐะฝะฐั‚ะฐ"; "state_event_room_remove" = "%1$@ ะฟั€ะตะผะฐั…ะฝะฐ %2$@"; @@ -921,6 +988,7 @@ "screen_dm_details_unblock_user" = "ะžั‚ะฑะปะพะบะธั€ะฐะฝะต ะฝะฐ ะฟะพั‚ั€ะตะฑะธั‚ะตะปั"; "screen_edit_poll_delete_confirmation_title" = "ะ˜ะทั‚ั€ะธะฒะฐะฝะต ะฝะฐ ะฐะฝะบะตั‚ะฐั‚ะฐ"; "screen_edit_poll_title" = "ะ ะตะดะฐะบั‚ะธั€ะฐะฝะต ะฝะฐ ะฐะฝะบะตั‚ะฐั‚ะฐ"; +"screen_identity_use_another_device" = "Use another device"; "screen_login_subtitle" = "Matrix ะต ะพั‚ะฒะพั€ะตะฝะฐ ะผั€ะตะถะฐ ะทะฐ ัะธะณัƒั€ะฝะฐ, ะดะตั†ะตะฝั‚ั€ะฐะปะธะทะธั€ะฐะฝะฐ ะบะพะผัƒะฝะธะบะฐั†ะธั."; "screen_qr_code_login_invalid_scan_state_retry_button" = "ะŸะพะฒั‚ะพั€ะตะฝ ะพะฟะธั‚"; "screen_report_content_block_user" = "ะ‘ะปะพะบะธั€ะฐะฝะต ะฝะฐ ะฟะพั‚ั€ะตะฑะธั‚ะตะปั"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "ะ˜ะทั…ะพะด"; "screen_signout_confirmation_dialog_title" = "ะ˜ะทั…ะพะด"; "screen_signout_preference_item" = "ะ˜ะทั…ะพะด"; -"screen_waitlist_message_success" = "ะ”ะพะฑั€ะต ะดะพัˆะปะธ ะฒ %1$@!"; diff --git a/ElementX/Resources/Localizations/bg.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/bg.lproj/Localizable.stringsdict index 2dcd289c62..4cfc90f2ad 100644 --- a/ElementX/Resources/Localizations/bg.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/bg.lproj/Localizable.stringsdict @@ -194,6 +194,22 @@ ะ“ั€ะตัˆะตะฝ PIN. ะ˜ะผะฐั‚ะต ะพั‰ะต %1$d ัˆะฐะฝัะฐ + 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 diff --git a/ElementX/Resources/Localizations/cs.lproj/Localizable.strings b/ElementX/Resources/Localizations/cs.lproj/Localizable.strings index 711daf2ab7..0966a7b0cf 100644 --- a/ElementX/Resources/Localizations/cs.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/cs.lproj/Localizable.strings @@ -27,17 +27,20 @@ "action_back" = "Zpฤ›t"; "action_call" = "Hovor"; "action_cancel" = "Zruลกit"; +"action_cancel_for_now" = "Prozatรญm zruลกit"; "action_choose_photo" = "Vybrat fotku"; "action_clear" = "Vymazat"; "action_close" = "Zavล™รญt"; "action_complete_verification" = "Dokonฤit ovฤ›ล™enรญ"; "action_confirm" = "Potvrdit"; +"action_confirm_password" = "Potvrdit heslo"; "action_continue" = "Pokraฤovat"; "action_copy" = "Kopรญrovat"; "action_copy_link" = "Kopรญrovat odkaz"; "action_copy_link_to_message" = "Kopรญrovat odkaz na zprรกvu"; "action_create" = "Vytvoล™it"; "action_create_a_room" = "Vytvoล™it mรญstnost"; +"action_deactivate" = "Deaktivovat"; "action_decline" = "Odmรญtnout"; "action_delete_poll" = "Odstranit hlasovรกnรญ"; "action_disable" = "Zakรกzat"; @@ -70,6 +73,7 @@ "action_ok" = "OK"; "action_open_settings" = "Otevล™รญt nastavenรญ"; "action_open_with" = "Otevล™รญt v aplikaci"; +"action_pin" = "Pin"; "action_quick_reply" = "Rychlรก odpovฤ›ฤ"; "action_quote" = "Citovat"; "action_react" = "Reagovat"; @@ -80,6 +84,7 @@ "action_report_bug" = "Nahlรกsit chybu"; "action_report_content" = "Nahlรกsit obsah"; "action_reset" = "Obnovit"; +"action_reset_identity" = "Obnovit identitu"; "action_retry" = "Zkusit znovu"; "action_retry_decryption" = "Opakovat deลกifrovรกnรญ"; "action_save" = "Uloลพit"; @@ -99,10 +104,18 @@ "action_take_photo" = "Vyfotit"; "action_tap_for_options" = "Klepnutรญm zobrazรญte moลพnosti"; "action_try_again" = "Zkusit znovu"; +"action_unpin" = "Odepnout"; +"action_view_in_timeline" = "Zobrazit na ฤasovรฉ ose"; "action_view_source" = "Zobrazit zdroj"; "action_yes" = "Ano"; "action.load_more" = "Naฤรญst vรญce"; -"action.pin" = "Pin"; +"action_deactivate_account" = "Deaktivovat รบฤet"; +"banner_migrate_to_native_sliding_sync_action" = "Odhlรกsit se a upgradovat"; +"banner_migrate_to_native_sliding_sync_description" = "Vรกลก server nynรญ podporuje novรฝ, rychlejลกรญ protokol. Chcete-li upgradovat, odhlaste se a znovu se pล™ihlaste. Pokud to udฤ›lรกte nynรญ, pomลฏลพe vรกm vyhnout se nucenรฉmu odhlรกลกenรญ, kdyลพ bude starรฝ protokol pozdฤ›ji odstranฤ›n."; +"banner_migrate_to_native_sliding_sync_force_logout_title" = "Vรกลก domovskรฝ server jiลพ nepodporuje starรฝ protokol. Chcete-li pokraฤovat v pouลพรญvรกnรญ aplikace, odhlaste se a znovu se pล™ihlaste."; +"banner_migrate_to_native_sliding_sync_title" = "Upgrade k dispozici"; +"banner.set_up_recovery.content" = "Vygenerujte novรฝ klรญฤ pro obnovenรญ, kterรฝ lze pouลพรญt k obnovenรญ historie ลกifrovanรฝch zprรกv v pล™รญpadฤ›, ลพe ztratรญte pล™รญstup ke svรฝm zaล™รญzenรญm."; +"banner.set_up_recovery.title" = "Nastavenรญ obnovy"; "common_about" = "O aplikaci"; "common_acceptable_use_policy" = "Zรกsady pouลพรญvรกnรญ"; "common_advanced_settings" = "Pokroฤilรก nastavenรญ"; @@ -214,6 +227,7 @@ "common_waiting_for_decryption_key" = "ฤŒekรกnรญ na deลกifrovacรญ klรญฤ"; "common.do_not_show_this_again" = "Znovu nezobrazovat"; "common.open_source_licenses" = "Licence s otevล™enรฝm zdrojovรฝm kรณdem"; +"common.pinned" = "Pล™ipnuto"; "common.send_to" = "Odeslat do"; "common_no_room_name" = "ลฝรกdnรฝ nรกzev mรญstnosti"; "common_poll_end_confirmation" = "Opravdu chcete ukonฤit toto hlasovรกnรญ?"; @@ -244,6 +258,7 @@ "emoji_picker_category_people" = "Smajlรญci a lidรฉ"; "emoji_picker_category_places" = "Cestovรกnรญ a mรญsta"; "emoji_picker_category_symbols" = "Symboly"; +"error_account_creation_not_possible" = "Vรกลก domovskรฝ server je tล™eba upgradovat, aby podporoval sluลพbu Matrix Authentication Service a vytvรกล™enรญ รบฤtu."; "error_failed_creating_the_permalink" = "Vytvoล™enรญ trvalรฉho odkazu se nezdaล™ilo"; "error_failed_loading_map" = "%1$@ nemohl naฤรญst mapu. Zkuste to prosรญm pozdฤ›ji."; "error_failed_loading_messages" = "Naฤรญtรกnรญ zprรกv se nezdaล™ilo"; @@ -253,10 +268,12 @@ "error_no_compatible_app_found" = "Nebyla nalezena ลพรกdnรก kompatibilnรญ aplikace, kterรก by tuto akci zpracovala."; "error_some_messages_have_not_been_sent" = "Nฤ›kterรฉ zprรกvy nebyly odeslรกny"; "error_unknown" = "Omlouvรกme se, doลกlo k chybฤ›"; -"event_shield_reason_authenticity_not_guaranteed" = "The authenticity of this encrypted message can't be guaranteed on this device."; -"event_shield_reason_unknown_device" = "Encrypted by an unknown or deleted device."; -"event_shield_reason_unsigned_device" = "Encrypted by a device not verified by its owner."; -"event_shield_reason_unverified_identity" = "Encrypted by an unverified user."; +"event_shield_reason_authenticity_not_guaranteed" = "Autenticitu tรฉto zaลกifrovanรฉ zprรกvy nelze na tomto zaล™รญzenรญ zaruฤit."; +"event_shield_reason_previously_verified" = "Zaลกifrovรกno dล™รญve ovฤ›ล™enรฝm uลพivatelem."; +"event_shield_reason_sent_in_clear" = "Nenรญ zaลกifrovรกno."; +"event_shield_reason_unknown_device" = "ล ifrovรกno neznรกmรฝm nebo smazanรฝm zaล™รญzenรญm."; +"event_shield_reason_unsigned_device" = "ล ifrovรกno zaล™รญzenรญm, kterรฉ nebylo ovฤ›ล™eno jeho vlastnรญkem."; +"event_shield_reason_unverified_identity" = "ล ifrovรกno neovฤ›ล™enรฝm uลพivatelem."; "full_screen_intent_banner_message" = "Abyste nikdy nezmeลกkali dลฏleลพitรฝ hovor, zmฤ›ลˆte nastavenรญ tak, abyste povolili oznรกmenรญ na celรฉ obrazovce, kdyลพ je telefon uzamฤen."; "full_screen_intent_banner_title" = "Vylepลกete si zรกลพitek z volรกnรญ"; "invite_friends_rich_title" = "๐Ÿ”๏ธ Pล™ipojte se ke mnฤ› na %1$@"; @@ -275,11 +292,14 @@ "notification_inline_reply_failed" = "** Nepodaล™ilo se odeslat - otevล™ete prosรญm mรญstnost"; "notification_invitation_action_reject" = "Odmรญtnout"; "notification_invite_body" = "Vรกs pozval(a) do chatu"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "notification_mentioned_you_body" = "Zmรญnili vรกs: %1$@"; "notification_new_messages" = "Novรฉ zprรกvy"; "notification_reaction_body" = "Reagoval(a) s %1$@"; "notification_room_invite_body" = "Vรกs pozval(a) do mรญstnosti"; +"notification_room_invite_body_with_sender" = "%1$@ invited you to join the room"; "notification_sender_me" = "Jรก"; +"notification_sender_mention_reply" = "%1$@ zmรญnil(a) nebo odpovฤ›dฤ›l(a)"; "notification_test_push_notification_content" = "Prohlรญลพรญte si oznรกmenรญ! Kliknฤ›te na mฤ›!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -312,10 +332,27 @@ "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_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_pinned_timeline_screen_title_empty" = "Pล™ipnutรฉ zprรกvy"; +"screen_reset_encryption_password_error" = "Doลกlo k neznรกmรฉ chybฤ›. Zkontrolujte, zda je heslo k รบฤtu sprรกvnรฉ a zkuste to znovu."; +"screen_resolve_send_failure_changed_identity_primary_button_title" = "Zruลกit ovฤ›ล™enรญ a odeslat"; +"screen_resolve_send_failure_changed_identity_subtitle" = "Ovฤ›ล™enรญ mลฏลพete zruลกit a pล™esto odeslat tuto zprรกvu, nebo mลฏลพete prozatรญm zruลกit a zkusit to znovu pozdฤ›ji po opฤ›tovnรฉm ovฤ›ล™enรญ %1$@."; +"screen_resolve_send_failure_changed_identity_title" = "Vaลกe zprรกva nebyla odeslรกna, protoลพe ovฤ›ล™enรก identita uลพivatele %1$@ se zmฤ›nila"; +"screen_resolve_send_failure_unsigned_device_primary_button_title" = "Pล™esto odeslat zprรกvu"; +"screen_resolve_send_failure_unsigned_device_subtitle" = "%1$@ pouลพรญvรก jedno nebo vรญce neovฤ›ล™enรฝch zaล™รญzenรญ. Zprรกvu mลฏลพete pล™esto odeslat, nebo mลฏลพete prozatรญm zruลกit a zkusit to znovu pozdฤ›ji potรฉ, co %2$@ ovฤ›ล™รญ vลกechna svรก zaล™รญzenรญ."; +"screen_resolve_send_failure_unsigned_device_title" = "Vaลกe zprรกva nebyla odeslรกna, protoลพe%1$@ neovฤ›ล™il(a) vลกechna zaล™รญzenรญ"; +"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.pinned_banner_indicator" = "%1$@ of %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ Pinned messages"; -"screen.room.pinned_banner_view_all_button_title" = "View All"; +"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_details_pinned_events_row_title" = "Pล™ipnutรฉ zprรกvy"; +"screen_timeline_item_menu_send_failure_changed_identity" = "Zprรกva nebyla odeslรกna, protoลพe ovฤ›ล™enรก identita uลพivatele %1$@ se zmฤ›nila."; +"screen_timeline_item_menu_send_failure_unsigned_device" = "Zprรกva nebyla odeslรกna, protoลพe%1$@ neovฤ›ล™il(a) vลกechna zaล™รญzenรญ."; +"screen_timeline_item_menu_send_failure_you_unsigned_device" = "Zprรกva nebyla odeslรกna, protoลพe jste neovฤ›ล™ili jedno nebo vรญce zaล™รญzenรญ."; "screen_account_provider_change" = "Zmฤ›na poskytovatele รบฤtu"; "screen_account_provider_form_hint" = "Adresa domovskรฉho serveru"; "screen_account_provider_form_notice" = "Zadejte hledanรฝ vรฝraz nebo adresu domรฉny."; @@ -398,6 +435,7 @@ "screen_chat_backup_recovery_action_confirm_description" = "Vaลกe zรกloha chatu nenรญ aktuรกlnฤ› synchronizovรกna."; "screen_chat_backup_recovery_action_setup" = "Nastavenรญ obnovy"; "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"; "screen_create_new_recovery_key_list_item_2" = "Znovu se pล™ihlaste ke svรฉmu รบฤtu"; "screen_create_new_recovery_key_list_item_3" = "Kdyลพ budete vyzvรกni k ovฤ›ล™enรญ vaลกeho zaล™รญzenรญ, vyberte %1$@"; @@ -421,6 +459,17 @@ "screen_create_room_public_option_description" = "Zprรกvy nejsou ลกifrovanรฉ a mลฏลพe si je pล™eฤรญst kdokoli. ล ifrovรกnรญ mลฏลพete povolit pozdฤ›ji."; "screen_create_room_public_option_title" = "Veล™ejnรก mรญstnost (kdokoli)"; "screen_create_room_topic_label" = "Tรฉma (nepovinnรฉ)"; +"screen_deactivate_account_confirmation_dialog_content" = "Potvrฤte prosรญm, ลพe chcete svลฏj รบฤet deaktivovat. Tuto akci nelze vrรกtit zpฤ›t."; +"screen_deactivate_account_delete_all_messages" = "Smazat vลกechny mรฉ zprรกvy"; +"screen_deactivate_account_delete_all_messages_notice" = "Upozornฤ›nรญ: Budoucรญ uลพivatelรฉ mohou vidฤ›t neรบplnรฉ konverzace."; +"screen_deactivate_account_description" = "Deaktivace vaลกeho รบฤtu je %1$@, coลพ zpลฏsobรญ:"; +"screen_deactivate_account_description_bold_part" = "nezvratnรก"; +"screen_deactivate_account_list_item_1" = "%1$@ vรกลก รบฤet (nemลฏลพete se znovu pล™ihlรกsit a vaลกe ID nelze znovu pouลพรญt)."; +"screen_deactivate_account_list_item_1_bold_part" = "Trvale zakรกzat"; +"screen_deactivate_account_list_item_2" = "Odebere vรกs ze vลกech chatovacรญch mรญstnostรญ."; +"screen_deactivate_account_list_item_3" = "Odstranรญ informace o vaลกem รบฤtu z naลกeho serveru identit."; +"screen_deactivate_account_list_item_4" = "Vaลกe zprรกvy budou stรกle viditelnรฉ registrovanรฝm uลพivatelลฏm, ale nebudou dostupnรฉ novรฝm ani neregistrovanรฝm uลพivatelลฏm, pokud se rozhodnete je smazat."; +"screen_deactivate_account_title" = "Deaktivovat รบฤet"; "screen_edit_poll_delete_confirmation" = "Opravdu chcete odstranit toto hlasovรกnรญ?"; "screen_edit_profile_display_name" = "Zobrazovanรฉ jmรฉno"; "screen_edit_profile_display_name_placeholder" = "Vaลกe zobrazovanรฉ jmรฉno"; @@ -428,12 +477,20 @@ "screen_edit_profile_error_title" = "Nelze aktualizovat profil"; "screen_edit_profile_title" = "Upravit profil"; "screen_edit_profile_updating_details" = "Aktualizace profilu..."; +"screen_encryption_reset_action_continue_reset" = "Pokraฤovat v resetovรกnรญ"; +"screen_encryption_reset_bullet_1" = "Podrobnosti o vaลกem รบฤtu, kontaktech, preferencรญch a seznamu chatu budou zachovรกny"; +"screen_encryption_reset_bullet_2" = "Ztratรญte svou stรกvajรญcรญ historii zprรกv"; +"screen_encryption_reset_bullet_3" = "Budete muset znovu ovฤ›ล™it vลกechna stรกvajรญcรญ zaล™รญzenรญ a kontakty"; +"screen_encryption_reset_footer" = "Obnovte svou identitu pouze v pล™รญpadฤ›, ลพe nemรกte pล™รญstup k jinรฉmu pล™ihlรกลกenรฉmu zaล™รญzenรญ a ztratili jste klรญฤ pro obnovenรญ."; +"screen_encryption_reset_title" = "Obnovte svou identitu v pล™รญpadฤ›, ลพe nemลฏลพete potvrdit jinรฝm zpลฏsobem"; +"screen_identity_confirmation_cannot_confirm" = "Nemลฏลพete potvrdit?"; "screen_identity_confirmation_create_new_recovery_key" = "Vytvoล™enรญ novรฉho klรญฤe pro obnovenรญ"; "screen_identity_confirmation_subtitle" = "Ovฤ›ล™te toto zaล™รญzenรญ a nastavte zabezpeฤenรฉ zasรญlรกnรญ zprรกv."; "screen_identity_confirmation_title" = "Potvrฤte, ลพe jste to vy"; +"screen_identity_confirmation_use_another_device" = "Pouลพรญt jinรฉ zaล™รญzenรญ"; +"screen_identity_confirmation_use_recovery_key" = "Pouลพรญt klรญฤ pro obnovenรญ"; "screen_identity_confirmed_subtitle" = "Nynรญ mลฏลพete bezpeฤnฤ› ฤรญst nebo odesรญlat zprรกvy, a kdokoli, s kรฝm chatujete, mลฏลพe tomuto zaล™รญzenรญ dลฏvฤ›ล™ovat."; "screen_identity_confirmed_title" = "Zaล™รญzenรญ ovฤ›ล™eno"; -"screen_identity_use_another_device" = "Pouลพรญt jinรฉ zaล™รญzenรญ"; "screen_identity_waiting_on_other_device" = "ฤŒekรกnรญ na jinรฉm zaล™รญzenรญ..."; "screen_invites_decline_chat_message" = "Opravdu chcete odmรญtnout pozvรกnku do %1$@?"; "screen_invites_decline_chat_title" = "Odmรญtnout pozvรกnรญ"; @@ -556,7 +613,6 @@ "screen_recovery_key_confirm_error_content" = "Zkuste prosรญm znovu potvrdit pล™รญstup k zรกloze chatu."; "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_label" = "Klรญฤ pro obnovenรญ nebo pล™รญstupovรฝ kรณd"; "screen_recovery_key_confirm_key_placeholder" = "Zadejte..."; "screen_recovery_key_confirm_lost_recovery_key" = "Ztratili jste klรญฤ pro obnovenรญ?"; "screen_recovery_key_confirm_success" = "Klรญฤ pro obnovenรญ potvrzen"; @@ -577,6 +633,14 @@ "screen_report_content_block_user_hint" = "Zaลกkrtnฤ›te, pokud chcete skrรฝt vลกechny aktuรกlnรญ a budoucรญ zprรกvy od tohoto uลพivatele"; "screen_report_content_explanation" = "Tato zprรกva bude nahlรกลกena sprรกvci vaลกeho domovskรฉho serveru. Nebude si moci pล™eฤรญst ลพรกdnรฉ ลกifrovanรฉ zprรกvy."; "screen_report_content_hint" = "Dลฏvod nahlรกลกenรญ tohoto obsahu"; +"screen_reset_encryption_confirmation_alert_action" = "Ano, resetovat nynรญ"; +"screen_reset_encryption_confirmation_alert_subtitle" = "Tento proces je nevratnรฝ."; +"screen_reset_encryption_confirmation_alert_title" = "Opravdu chcete obnovit ลกifrovรกnรญ?"; +"screen_reset_encryption_password_placeholder" = "Zadat..."; +"screen_reset_encryption_password_subtitle" = "Potvrฤte, ลพe chcete obnovit ลกifrovรกnรญ."; +"screen_reset_encryption_password_title" = "Pro pokraฤovรกnรญ zadejte heslo k รบฤtu"; +"screen_reset_identity_confirmation_subtitle" = "Chystรกte se pล™ejรญt na svลฏj %1$@ รบฤet a obnovit svou identitu. Potรฉ budete pล™esmฤ›rovรกni zpฤ›t do aplikace."; +"screen_reset_identity_confirmation_title" = "Nemลฏลพete to potvrdit? Pล™ejdฤ›te na svลฏj รบฤet a resetujte svou identitu."; "screen_room_alias_resolver_resolve_alias_failure" = "Nepodaล™ilo se pล™eloลพit alias mรญstnosti."; "screen_room_attachment_source_camera" = "Fotoaparรกt"; "screen_room_attachment_source_camera_video" = "Natoฤit video"; @@ -775,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "Uloลพili jste si klรญฤ pro obnovenรญ?"; "screen_start_chat_error_starting_chat" = "Pล™i pokusu o zahรกjenรญ chatu doลกlo k chybฤ›"; "screen_view_location_title" = "Poloha"; -"screen_waitlist_message" = "Na %2$@ je momentรกlnฤ› vysokรก poptรกvka po %1$@. Vraลฅte se do aplikace za pรกr dnรญ a zkuste to znovu.\n\nDรญky za trpฤ›livost!"; -"screen_waitlist_title" = "Jste v poล™adnรญku!"; -"screen_waitlist_title_success" = "Jdete do toho!"; "screen_welcome_bullet_1" = "Hovory, hlasovรกnรญ, vyhledรกvรกnรญ a dalลกรญ budou pล™idรกny koncem tohoto roku."; "screen_welcome_bullet_2" = "Historie zprรกv ลกifrovanรฝch mรญstnostรญ nebude v tรฉto aktualizaci k dispozici."; "screen_welcome_bullet_3" = "Rรกdi bychom se od vรกs dozvฤ›dฤ›li, co si o tom myslรญte, dejte nรกm vฤ›dฤ›t prostล™ednictvรญm strรกnky s nastavenรญm."; @@ -834,6 +895,12 @@ "state_event_room_name_removed_by_you" = "Odstranili jste nรกzev mรญstnosti"; "state_event_room_none" = "%1$@ neprovedl(a) ลพรกdnรฉ zmฤ›ny"; "state_event_room_none_by_you" = "Neprovedli jste ลพรกdnรฉ zmฤ›ny"; +"state_event_room_pinned_events_changed" = "%1$@ zmฤ›nil(a) pล™ipnutรฉ zprรกvy"; +"state_event_room_pinned_events_changed_by_you" = "Zmฤ›nili jste pล™ipnutรฉ zprรกvy"; +"state_event_room_pinned_events_pinned" = "%1$@ pล™ipnul(a) zprรกvu"; +"state_event_room_pinned_events_pinned_by_you" = "Pล™ipnuli jste zprรกvu"; +"state_event_room_pinned_events_unpinned" = "%1$@ odepnul(a) zprรกvu"; +"state_event_room_pinned_events_unpinned_by_you" = "Odepnuli jste zprรกvu"; "state_event_room_reject" = "%1$@ pozvรกnku odmรญtl(a)"; "state_event_room_reject_by_you" = "Odmรญtli jste pozvรกnรญ"; "state_event_room_remove" = "%1$@ odebral(a) %2$@"; @@ -921,6 +988,7 @@ "screen_dm_details_unblock_user" = "Odblokovat uลพivatele"; "screen_edit_poll_delete_confirmation_title" = "Odstranit hlasovรกnรญ"; "screen_edit_poll_title" = "Upravit hlasovรกnรญ"; +"screen_identity_use_another_device" = "Pouลพรญt jinรฉ zaล™รญzenรญ"; "screen_login_subtitle" = "Matrix je otevล™enรก sรญลฅ pro bezpeฤnou a decentralizovanou komunikaci."; "screen_qr_code_login_invalid_scan_state_retry_button" = "Zkusit znovu"; "screen_report_content_block_user" = "Zablokovat uลพivatele"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "Odhlรกsit se"; "screen_signout_confirmation_dialog_title" = "Odhlรกsit se"; "screen_signout_preference_item" = "Odhlรกsit se"; -"screen_waitlist_message_success" = "Vรญtรก vรกs %1$@!"; diff --git a/ElementX/Resources/Localizations/cs.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/cs.lproj/Localizable.stringsdict index 206e17cd87..4362b120c3 100644 --- a/ElementX/Resources/Localizations/cs.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/cs.lproj/Localizable.stringsdict @@ -218,6 +218,24 @@ ล patnรฝ PIN. Mรกte %1$d dalลกรญch pokusลฏ + screen_pinned_timeline_screen_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d Pล™ipnutรก zprรกva + few + %1$d Pล™ipnutรฉ zprรกvy + other + %1$d Pล™ipnutรฝch zprรกv + + screen_room_member_list_header_title NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/de.lproj/Localizable.strings b/ElementX/Resources/Localizations/de.lproj/Localizable.strings index b5758ab89f..aea080e28b 100644 --- a/ElementX/Resources/Localizations/de.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/de.lproj/Localizable.strings @@ -27,17 +27,20 @@ "action_back" = "Zurรผck"; "action_call" = "Anruf"; "action_cancel" = "Abbrechen"; +"action_cancel_for_now" = "Jetzt abbrechen"; "action_choose_photo" = "Foto auswรคhlen"; "action_clear" = "Lรถschen"; "action_close" = "SchlieรŸen"; "action_complete_verification" = "Verifizierung abschlieรŸen"; "action_confirm" = "Bestรคtigen"; +"action_confirm_password" = "Confirm password"; "action_continue" = "Weiter"; "action_copy" = "Kopieren"; "action_copy_link" = "Link kopieren"; "action_copy_link_to_message" = "Link zur Nachricht kopieren"; "action_create" = "Erstellen"; "action_create_a_room" = "Raum erstellen"; +"action_deactivate" = "Deactivate"; "action_decline" = "Ablehnen"; "action_delete_poll" = "Umfrage lรถschen"; "action_disable" = "Deaktivieren"; @@ -70,6 +73,7 @@ "action_ok" = "Ok"; "action_open_settings" = "Einstellungen รถffnen"; "action_open_with" = "ร–ffnen mit"; +"action_pin" = "Fixieren"; "action_quick_reply" = "Schnelle Antwort"; "action_quote" = "Zitat"; "action_react" = "Reagieren"; @@ -80,6 +84,7 @@ "action_report_bug" = "Fehler melden"; "action_report_content" = "Inhalt melden"; "action_reset" = "Zurรผcksetzen"; +"action_reset_identity" = "Reset identity"; "action_retry" = "Erneut versuchen"; "action_retry_decryption" = "Entschlรผsselung wiederholen"; "action_save" = "Speichern"; @@ -99,10 +104,18 @@ "action_take_photo" = "Foto aufnehmen"; "action_tap_for_options" = "Fรผr Optionen tippen"; "action_try_again" = "Erneut versuchen"; +"action_unpin" = "Lรถsen"; +"action_view_in_timeline" = "Im Chatverlauf anzeigen"; "action_view_source" = "Quellcode anzeigen"; "action_yes" = "Ja"; "action.load_more" = "Mehr laden ..."; -"action.pin" = "Pin"; +"action_deactivate_account" = "Deactivate account"; +"banner_migrate_to_native_sliding_sync_action" = "Abmelden und aktualisieren"; +"banner_migrate_to_native_sliding_sync_description" = "Dein Server unterstรผtzt jetzt ein neues, schnelleres Protokoll. Melde dich ab und melde dich wieder an, um zu aktualisieren. Wenn du das jetzt tust, vermeidest du eine erzwungene Abmeldung, wenn das alte Protokoll spรคter entfernt wird."; +"banner_migrate_to_native_sliding_sync_force_logout_title" = "Dein Homeserver unterstรผtzt das alte Protokoll nicht mehr. Bitte logge dich aus und melde dich wieder an, um die App weiter zu nutzen."; +"banner_migrate_to_native_sliding_sync_title" = "Aktualisierung verfรผgbar"; +"banner.set_up_recovery.content" = "Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices."; +"banner.set_up_recovery.title" = "Wiederherstellung einrichten"; "common_about" = "รœber"; "common_acceptable_use_policy" = "Nutzungsrichtlinie"; "common_advanced_settings" = "Erweiterte Einstellungen"; @@ -112,7 +125,7 @@ "common_blocked_users" = "Blockierte Nutzer"; "common_bubbles" = "Sprechblasen"; "common_call_invite" = "Aktiver Anruf (nicht unterstรผtzt)"; -"common_call_started" = "Call started"; +"common_call_started" = "Aufruf gestartet"; "common_chat_backup" = "Chat-Backup"; "common_copyright" = "Copyright"; "common_creating_room" = "Raum wird erstellt..."; @@ -212,9 +225,10 @@ "common_voice_message" = "Sprachnachricht"; "common_waiting" = "Wartenโ€ฆ"; "common_waiting_for_decryption_key" = "Warte auf diese Nachricht"; -"common.do_not_show_this_again" = "Do not show this again"; -"common.open_source_licenses" = "Open source licenses"; -"common.send_to" = "Send to"; +"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_no_room_name" = "Kein Raumname"; "common_poll_end_confirmation" = "Bist du sicher, dass du diese Umfrage beenden mรถchtest?"; "common_poll_summary" = "Umfrage: %1$@"; @@ -244,6 +258,7 @@ "emoji_picker_category_people" = "Smileys & Menschen"; "emoji_picker_category_places" = "Reisen & Orte"; "emoji_picker_category_symbols" = "Symbole"; +"error_account_creation_not_possible" = "Dein Homeserver muss aktualisiert werden, um den Matrix Authentication Services und die Erstellung von Konten zu unterstรผtzen."; "error_failed_creating_the_permalink" = "Fehler beim Erstellen des Permalinks"; "error_failed_loading_map" = "%1$@ konnte die Karte nicht laden. Bitte versuche es spรคter erneut."; "error_failed_loading_messages" = "Fehler beim Laden der Nachrichten"; @@ -253,12 +268,14 @@ "error_no_compatible_app_found" = "Fรผr diese Aktion wurde keine kompatible App gefunden."; "error_some_messages_have_not_been_sent" = "Einige Nachrichten wurden nicht gesendet"; "error_unknown" = "Entschuldigung, es ist ein Fehler aufgetreten"; -"event_shield_reason_authenticity_not_guaranteed" = "The authenticity of this encrypted message can't be guaranteed on this device."; -"event_shield_reason_unknown_device" = "Encrypted by an unknown or deleted device."; -"event_shield_reason_unsigned_device" = "Encrypted by a device not verified by its owner."; -"event_shield_reason_unverified_identity" = "Encrypted by an unverified user."; -"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_title" = "Enhance your call experience"; +"event_shield_reason_authenticity_not_guaranteed" = "Die Authentizitรคt dieser verschlรผsselten Nachricht kann auf diesem Gerรคt nicht garantiert werden."; +"event_shield_reason_previously_verified" = "Verschlรผsselt von einem zuvor verifizierten Nutzer."; +"event_shield_reason_sent_in_clear" = "Unverschlรผsselt."; +"event_shield_reason_unknown_device" = "Verschlรผsselt von einem unbekannten oder gelรถschten Gerรคt."; +"event_shield_reason_unsigned_device" = "Verschlรผsselt durch ein Gerรคt, das nicht von seinem Besitzer verifiziert wurde."; +"event_shield_reason_unverified_identity" = "Verschlรผsselt durch einen nicht verifizierten Benutzer."; +"full_screen_intent_banner_message" = "Damit du keinen wichtigen Anruf verpasst, รคndere bitte deine Einstellungen so, dass du bei gesperrtem Telefon Benachrichtigungen im Vollbildmodus erhรคltst."; +"full_screen_intent_banner_title" = "Verbessere dein Anruferlebnis"; "invite_friends_rich_title" = "๐Ÿ”๏ธ Begleite mich auf %1$@"; "invite_friends_text" = "Hey, sprich mit mir auf %1$@: %2$@"; "leave_conversation_alert_subtitle" = "Bist du sicher, dass du diese Unterhaltung verlassen willst? Diese Unterhaltung ist nicht รถffentlich und du kannst ihr ohne Einladung nicht wieder beitreten."; @@ -269,17 +286,20 @@ "notification_channel_call" = "Anruf"; "notification_channel_listening_for_events" = "Auf Ereignisse achten"; "notification_channel_noisy" = "Laute Benachrichtigungen"; -"notification_channel_ringing_calls" = "Ringing calls"; +"notification_channel_ringing_calls" = "Klingelnde Anrufe"; "notification_channel_silent" = "Stumme Benachrichtigungen"; -"notification_incoming_call" = "Incoming call"; +"notification_incoming_call" = "Eingehender Anruf"; "notification_inline_reply_failed" = "** Fehler beim Senden - bitte Raum รถffnen"; "notification_invitation_action_reject" = "Ablehnen"; "notification_invite_body" = "Du wurdest zu einem Chat eingeladen"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "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_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!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -312,10 +332,27 @@ "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_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_pinned_timeline_screen_title_empty" = "Fixierte Nachrichten"; +"screen_reset_encryption_password_error" = "Es ist ein unbekannter Fehler aufgetreten. Bitte รผberprรผfe das Passwort deines Kontos und versuche es erneut."; +"screen_resolve_send_failure_changed_identity_primary_button_title" = "Verifizierung zurรผckziehen und senden"; +"screen_resolve_send_failure_changed_identity_subtitle" = "Du kannst deine Verifizierung zurรผckziehen und diese Nachricht trotzdem senden, oder du kannst sie vorerst abbrechen und es spรคter noch einmal versuchen, nachdem du %1$@ erneut verifiziert hast."; +"screen_resolve_send_failure_changed_identity_title" = "Deine Nachricht wurde nicht gesendet, da sich die verifizierte Identitรคt von %1$@ geรคndert hat"; +"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_room_mentions_at_room_subtitle" = "Alle Mitglieder benachrichtigen"; -"screen.room.pinned_banner_indicator" = "%1$@ of %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ Pinned messages"; -"screen.room.pinned_banner_view_all_button_title" = "View All"; +"screen_room_pinned_banner_indicator" = "%1$@ von %2$@"; +"screen_room_pinned_banner_indicator_description" = "%1$@ Angepinnte Nachrichten"; +"screen_room_pinned_banner_loading_description" = "Nachricht wird geladenโ€ฆ"; +"screen_room_pinned_banner_view_all_button_title" = "Alle anzeigen"; +"screen_room_details_pinned_events_row_title" = "Fixierte Nachrichten"; +"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_account_provider_change" = "Kontoanbieter รคndern"; "screen_account_provider_form_hint" = "Homeserver-Adresse"; "screen_account_provider_form_notice" = "Gib einen Suchbegriff oder eine Domainadresse ein."; @@ -398,6 +435,7 @@ "screen_chat_backup_recovery_action_confirm_description" = "Dein Chat-Backup ist derzeit nicht synchronisiert."; "screen_chat_backup_recovery_action_setup" = "Wiederherstellung einrichten"; "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"; "screen_create_new_recovery_key_list_item_2" = "Melde dich erneut bei deinem Konto an"; "screen_create_new_recovery_key_list_item_3" = "Wenn du aufgefordert wirst dein Gerรคt zu verifizieren, wรคhle \"%1$@\"."; @@ -421,6 +459,17 @@ "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_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_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"; @@ -428,12 +477,20 @@ "screen_edit_profile_error_title" = "Profil kann nicht aktualisiert werden"; "screen_edit_profile_title" = "Profil bearbeiten"; "screen_edit_profile_updating_details" = "Profil wird aktualisiert..."; +"screen_encryption_reset_action_continue_reset" = "Zurรผcksetzen fortsetzen"; +"screen_encryption_reset_bullet_1" = "Your account details, contacts, preferences, and chat list will be kept"; +"screen_encryption_reset_bullet_2" = "You will lose your existing message history"; +"screen_encryption_reset_bullet_3" = "You will need to verify all your existing devices and contacts again"; +"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_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"; +"screen_identity_confirmation_use_another_device" = "Ein anderes Gerรคt verwenden"; +"screen_identity_confirmation_use_recovery_key" = "Wiederherstellungsschlรผssel verwenden"; "screen_identity_confirmed_subtitle" = "Du kannst nun verschlรผsselte Nachrichten lesen oder versenden."; "screen_identity_confirmed_title" = "Gerรคt verifiziert"; -"screen_identity_use_another_device" = "Ein anderes Gerรคt verwenden"; "screen_identity_waiting_on_other_device" = "Bitte warten bis das andere Gerรคt bereit ist."; "screen_invites_decline_chat_message" = "Mรถchtest du die Einladung zum Betreten von %1$@ wirklich ablehnen?"; "screen_invites_decline_chat_title" = "Einladung ablehnen"; @@ -452,9 +509,9 @@ "screen_key_backup_disable_confirmation_action_turn_off" = "Ausschalten"; "screen_key_backup_disable_confirmation_description" = "Du verlierst deine verschlรผsselten Nachrichten, wenn du auf allen Gerรคten abgemeldet bist."; "screen_key_backup_disable_confirmation_title" = "Bist du sicher, dass du das Backup deaktivieren willst?"; -"screen_key_backup_disable_description" = "Wenn du das Backup deaktivierst, wird dein aktuelles Backup des Verschlรผsselungsschlรผssels entfernt und andere Sicherheitsfunktionen werden deaktiviert. \nDas bedeutet:"; -"screen_key_backup_disable_description_point_1" = "Keine Historie fรผr verschlรผsselte Nachrichten auf neuen Gerรคten ."; -"screen_key_backup_disable_description_point_2" = "Du verlierst den Zugriff auf deine verschlรผsselten Nachrichten, wenn du dich รผberall von %1$@ abmeldest"; +"screen_key_backup_disable_description" = "Wenn du das Backup deaktivierst, wird dein aktuelles Schlรผssel Backup fรผr die Verschlรผsselung entfernt und andere Sicherheitsfunktionen werden deaktiviert. Das bedeutet:"; +"screen_key_backup_disable_description_point_1" = "Keinen Nachrichtenverlauf fรผr verschlรผsselte Nachrichten auf neuen Gerรคten ."; +"screen_key_backup_disable_description_point_2" = "Verlust des Zugriffs auf Deine verschlรผsselten Nachrichten, wenn Du Dich รผberall von %1$@ abmeldest"; "screen_key_backup_disable_title" = "Bist du sicher, dass du das Backup deaktivieren willst?"; "screen_login_error_deactivated_account" = "Dieses Konto wurde deaktiviert."; "screen_login_error_invalid_credentials" = "Falscher Benutzername und/oder Passwort"; @@ -480,7 +537,7 @@ "screen_notification_settings_edit_failed_updating_default_mode" = "Beim Aktualisieren der Benachrichtigungseinstellungen ist ein Fehler aufgetreten."; "screen_notification_settings_edit_mode_all_messages" = "Alle Nachrichten"; "screen_notification_settings_edit_mode_mentions_and_keywords" = "Nur Erwรคhnungen und Schlรผsselwรถrter"; -"screen_notification_settings_edit_screen_direct_section_header" = "Benachrichtige mich bei Direktnachrichten รผber "; +"screen_notification_settings_edit_screen_direct_section_header" = "Benachrichtige mich bei Direktnachrichten รผber"; "screen_notification_settings_edit_screen_group_section_header" = "Bei Gruppenchats benachrichtige mich bei"; "screen_notification_settings_enable_notifications" = "Benachrichtigungen auf diesem Gerรคt aktivieren"; "screen_notification_settings_failed_fixing_configuration" = "Die Konfiguration wurde nicht korrigiert, bitte versuche es erneut."; @@ -516,18 +573,18 @@ "screen_qr_code_login_connection_note_secure_state_title" = "Die Verbindung ist nicht sicher"; "screen_qr_code_login_device_code_subtitle" = "Du wirst aufgefordert, die beiden unten abgebildeten Ziffern einzugeben."; "screen_qr_code_login_device_code_title" = "Trage die unten angezeigte Zahl auf einem anderen Device ein"; -"screen_qr_code_login_device_not_signed_in_scan_state_description" = "Sign in to your other device and then try again, or use another device thatโ€™s already signed in."; -"screen_qr_code_login_device_not_signed_in_scan_state_subtitle" = "Other device not signed in"; -"screen_qr_code_login_error_cancelled_subtitle" = "The sign in was cancelled on the other device."; -"screen_qr_code_login_error_cancelled_title" = "Sign in request cancelled"; -"screen_qr_code_login_error_declined_subtitle" = "The sign in was declined on the other device."; -"screen_qr_code_login_error_declined_title" = "Sign in declined"; -"screen_qr_code_login_error_expired_subtitle" = "Sign in expired. Please try again."; -"screen_qr_code_login_error_expired_title" = "The sign in was not completed in time"; -"screen_qr_code_login_error_linking_not_suported_subtitle" = "Your other device does not support signing in to %@ with a QR code.\n\nTry signing in manually, or scan the QR code with another device."; -"screen_qr_code_login_error_linking_not_suported_title" = "QR code not supported"; -"screen_qr_code_login_error_sliding_sync_not_supported_subtitle" = "Your account provider does not support %1$@."; -"screen_qr_code_login_error_sliding_sync_not_supported_title" = "%1$@ not supported"; +"screen_qr_code_login_device_not_signed_in_scan_state_description" = "Melde dich auf deinem anderen Gerรคt an und versuche es dann noch einmal oder verwende ein anderes Gerรคt, das bereits angemeldet ist."; +"screen_qr_code_login_device_not_signed_in_scan_state_subtitle" = "Anderes Gerรคt ist nicht angemeldet"; +"screen_qr_code_login_error_cancelled_subtitle" = "Die Anmeldung wurde auf dem anderen Gerรคt abgebrochen."; +"screen_qr_code_login_error_cancelled_title" = "Anmeldeanfrage abgebrochen"; +"screen_qr_code_login_error_declined_subtitle" = "Die Anmeldung auf dem anderen Gerรคt wurde abgelehnt."; +"screen_qr_code_login_error_declined_title" = "Anmelden abgelehnt"; +"screen_qr_code_login_error_expired_subtitle" = "Die Anmeldung ist abgelaufen. Bitte versuchen Sie es erneut."; +"screen_qr_code_login_error_expired_title" = "Die Anmeldung wurde nicht rechtzeitig abgeschlossen"; +"screen_qr_code_login_error_linking_not_suported_subtitle" = "Dein anderes Gerรคt unterstรผtzt die Anmeldung bei %@ mit einem QR-Code nicht.\n\nVersuche, dich manuell anzumelden, oder scanne den QR-Code mit einem anderen Gerรคt."; +"screen_qr_code_login_error_linking_not_suported_title" = "QR-Code wird nicht unterstรผtzt"; +"screen_qr_code_login_error_sliding_sync_not_supported_subtitle" = "Ihr Kontoanbieter unterstรผtzt %1$@ nicht."; +"screen_qr_code_login_error_sliding_sync_not_supported_title" = "%1$@wird nicht unterstรผtzt"; "screen_qr_code_login_initial_state_button_title" = "Bereit zum Scannen"; "screen_qr_code_login_initial_state_item_1" = "%1$@ auf einem Desktop-Gerรคt รถffnen"; "screen_qr_code_login_initial_state_item_2" = "Klick auf deinen Avatar"; @@ -556,7 +613,6 @@ "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_title" = "Falscher Wiederherstellungsschlรผssel"; "screen_recovery_key_confirm_key_description" = "Dies funktioniert auch mit einem Sicherheitsschlรผssel oder Sicherheitsphrase."; -"screen_recovery_key_confirm_key_label" = "Wiederherstellungsschlรผssel oder Passcode"; "screen_recovery_key_confirm_key_placeholder" = "Eingeben..."; "screen_recovery_key_confirm_lost_recovery_key" = "Hast du deinen Wiederherstellungschlรผssel vergessen?"; "screen_recovery_key_confirm_success" = "Wiederherstellungsschlรผssel bestรคtigt"; @@ -577,6 +633,14 @@ "screen_report_content_block_user_hint" = "Prรผfe, ob du alle aktuellen und zukรผnftigen Nachrichten dieses Benutzers ausblenden mรถchtest"; "screen_report_content_explanation" = "Diese Meldung wird an den Administrator deines Homeservers weitergeleitet. Dieser kann keine verschlรผsselten Nachrichten lesen."; "screen_report_content_hint" = "Grund fรผr die Meldung dieses Inhalts"; +"screen_reset_encryption_confirmation_alert_action" = "Yes, reset now"; +"screen_reset_encryption_confirmation_alert_subtitle" = "This process is irreversible."; +"screen_reset_encryption_confirmation_alert_title" = "Are you sure you want to reset your identity?"; +"screen_reset_encryption_password_placeholder" = "Eingeben..."; +"screen_reset_encryption_password_subtitle" = "Confirm that you want to reset your identity."; +"screen_reset_encryption_password_title" = "Enter your account password to continue"; +"screen_reset_identity_confirmation_subtitle" = "Du wirst jetzt zu deinem %1$@ Konto geleitet, um deine Identitรคt zurรผckzusetzen. Danach wirst du zur App zurรผckgebracht."; +"screen_reset_identity_confirmation_title" = "Kannst du das nicht bestรคtigen? Gehe zu deinem Konto, um deine Identitรคt zurรผckzusetzen."; "screen_room_alias_resolver_resolve_alias_failure" = "Der Raum-Alias konnte nicht ermittelt werden."; "screen_room_attachment_source_camera" = "Kamera"; "screen_room_attachment_source_camera_video" = "Video aufnehmen"; @@ -775,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "Hast du deinen Wiederherstellungsschlรผssel gespeichert?"; "screen_start_chat_error_starting_chat" = "Beim Versuch, einen Chat zu starten, ist ein Fehler aufgetreten"; "screen_view_location_title" = "Standort"; -"screen_waitlist_message" = "Derzeit besteht eine hohe Nachfrage nach %1$@ auf %2$@. Kehre in ein paar Tagen zur App zurรผck und versuche es erneut.\n\nDanke fรผr deine Geduld!"; -"screen_waitlist_title" = "Du bist fast am Ziel."; -"screen_waitlist_title_success" = "Du bist dabei."; "screen_welcome_bullet_1" = "Anrufe, Umfragen, Suchfunktionen und mehr werden im Laufe des Jahres hinzugefรผgt."; "screen_welcome_bullet_2" = "Der Nachrichtenverlauf fรผr verschlรผsselte Rรคume wird in diesem Update nicht verfรผgbar sein."; "screen_welcome_bullet_3" = "Wir wรผrden uns freuen, von dir zu hรถren. Teile uns deine Meinung รผber die Einstellungsseite mit."; @@ -834,6 +895,12 @@ "state_event_room_name_removed_by_you" = "Du hast den Raum-Namen entfernt"; "state_event_room_none" = "%1$@hat keine ร„nderungen vorgenommen"; "state_event_room_none_by_you" = "Du hast keine ร„nderungen vorgenommen"; +"state_event_room_pinned_events_changed" = "%1$@ hat die fixierten Nachrichten geรคndert"; +"state_event_room_pinned_events_changed_by_you" = "Du hast die fixierten Nachrichten geรคndert"; +"state_event_room_pinned_events_pinned" = "%1$@ fixierte eine Nachricht"; +"state_event_room_pinned_events_pinned_by_you" = "Du hast eine Nachricht fixiert"; +"state_event_room_pinned_events_unpinned" = "%1$@ lรถste eine Nachricht"; +"state_event_room_pinned_events_unpinned_by_you" = "Du hast eine Nachricht gelรถst"; "state_event_room_reject" = "%1$@ hat die Einladung abgelehnt"; "state_event_room_reject_by_you" = "Du hast die Einladung abgelehnt"; "state_event_room_remove" = "%1$@ hat %2$@ entfernt"; @@ -921,6 +988,7 @@ "screen_dm_details_unblock_user" = "Blockierung aufheben"; "screen_edit_poll_delete_confirmation_title" = "Umfrage lรถschen"; "screen_edit_poll_title" = "Umfrage bearbeiten"; +"screen_identity_use_another_device" = "Ein anderes Gerรคt verwenden"; "screen_login_subtitle" = "Matrix ist ein offenes Netzwerk fรผr eine sichere, dezentrale Kommunikation."; "screen_qr_code_login_invalid_scan_state_retry_button" = "Erneut versuchen"; "screen_report_content_block_user" = "Benutzer blockieren"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "Abmelden"; "screen_signout_confirmation_dialog_title" = "Abmelden"; "screen_signout_preference_item" = "Abmelden"; -"screen_waitlist_message_success" = "Willkommen bei %1$@!"; diff --git a/ElementX/Resources/Localizations/de.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/de.lproj/Localizable.stringsdict index 67bb7ee1d7..a0b5aa8da7 100644 --- a/ElementX/Resources/Localizations/de.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/de.lproj/Localizable.stringsdict @@ -189,9 +189,25 @@ NSStringFormatValueTypeKey d one - Falsche PIN. Du hast %1$d weitere Chance + Falsche PIN. Du hast %1$d weiteren Versuch other - Falsche PIN. Du hast %1$d weitere Chancen + Falsche PIN. Du hast %1$d weitere Versuche + + + screen_pinned_timeline_screen_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d fixierte Nachricht + other + %1$d fixierte Nachrichten screen_room_member_list_header_title diff --git a/ElementX/Resources/Localizations/el.lproj/Localizable.strings b/ElementX/Resources/Localizations/el.lproj/Localizable.strings index a6ad9cf7bc..b4570d38a9 100644 --- a/ElementX/Resources/Localizations/el.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/el.lproj/Localizable.strings @@ -27,17 +27,20 @@ "action_back" = "ฮ ฮฏฯƒฯ‰"; "action_call" = "ฮšฮฌฮปฮตฯƒฮต"; "action_cancel" = "ฮ†ฮบฯ…ฯฮฟ"; +"action_cancel_for_now" = "ฮ‘ฮบฯฯฯ‰ฯƒฮท ฯ€ฯฮฟฯ‚ ฯ„ฮฟ ฯ€ฮฑฯฯŒฮฝ"; "action_choose_photo" = "ฮ•ฯ€ฮนฮปฮฟฮณฮฎ ฯ†ฯ‰ฯ„ฮฟฮณฯฮฑฯ†ฮฏฮฑฯ‚"; "action_clear" = "ฮ•ฮบฮบฮฑฮธฮฌฯฮนฯƒฮท"; "action_close" = "ฮšฮปฮตฮฏฯƒฮนฮผฮฟ"; "action_complete_verification" = "ฮŸฮปฮฟฮบฮปฮฎฯฯ‰ฯƒฮท ฮตฯ€ฮฑฮปฮฎฮธฮตฯ…ฯƒฮทฯ‚"; "action_confirm" = "ฮ•ฯ€ฮนฮฒฮตฮฒฮฑฮฏฯ‰ฯƒฮท"; +"action_confirm_password" = "ฮ•ฯ€ฮนฮฒฮตฮฒฮฑฮฏฯ‰ฯƒฮท ฮบฯ‰ฮดฮนฮบฮฟฯ ฯ€ฯฯŒฯƒฮฒฮฑฯƒฮทฯ‚"; "action_continue" = "ฮฃฯ…ฮฝฮญฯ‡ฮตฮนฮฑ"; "action_copy" = "ฮ‘ฮฝฯ„ฮนฮณฯฮฑฯ†ฮฎ"; "action_copy_link" = "ฮ‘ฮฝฯ„ฮนฮณฯฮฑฯ†ฮฎ ฯƒฯ…ฮฝฮดฮญฯƒฮผฮฟฯ…"; "action_copy_link_to_message" = "ฮ‘ฮฝฯ„ฮนฮณฯฮฑฯ†ฮฎ ฯƒฯ…ฮฝฮดฮญฯƒฮผฮฟฯ… ฯƒฯ„ฮฟ ฮผฮฎฮฝฯ…ฮผฮฑ"; "action_create" = "ฮ”ฮทฮผฮนฮฟฯ…ฯฮณฮฏฮฑ"; "action_create_a_room" = "ฮ”ฮทฮผฮนฮฟฯฯฮณฮทฯƒฮต ฮญฮฝฮฑ ฮดฯ‰ฮผฮฌฯ„ฮนฮฟ"; +"action_deactivate" = "ฮ‘ฯ€ฮตฮฝฮตฯฮณฮฟฯ€ฮฟฮฏฮทฯƒฮท"; "action_decline" = "ฮ‘ฯ€ฯŒฯฯฮนฯˆฮท"; "action_delete_poll" = "ฮ”ฮนฮฑฮณฯฮฑฯ†ฮฎ ฮ”ฮทฮผฮฟฯƒฮบฯŒฯ€ฮทฯƒฮทฯ‚"; "action_disable" = "ฮ‘ฯ€ฮตฮฝฮตฯฮณฮฟฯ€ฮฟฮฏฮทฯƒฮท"; @@ -70,6 +73,7 @@ "action_ok" = "OK"; "action_open_settings" = "ฮกฯ…ฮธฮผฮฏฯƒฮตฮนฯ‚"; "action_open_with" = "ฮ†ฮฝฮฟฮนฮณฮผฮฑ ฮผฮต"; +"action_pin" = "ฮšฮฑฯฯ†ฮฏฯ„ฯƒฯ‰ฮผฮฑ"; "action_quick_reply" = "ฮ“ฯฮฎฮณฮฟฯฮท ฮฑฯ€ฮฌฮฝฯ„ฮทฯƒฮท"; "action_quote" = "ฮ ฮฑฯฮฌฮธฮตฯƒฮท"; "action_react" = "ฮ‘ฮฝฯ„ฮญฮดฯฮฑฯƒฮต"; @@ -80,6 +84,7 @@ "action_report_bug" = "ฮ‘ฮฝฮฑฯ†ฮฟฯฮฌ ฯƒฯ†ฮฌฮปฮผฮฑฯ„ฮฟฯ‚"; "action_report_content" = "ฮ‘ฮฝฮฑฯ†ฮฟฯฮฌ ฯ€ฮตฯฮนฮตฯ‡ฮฟฮผฮญฮฝฮฟฯ…"; "action_reset" = "ฮ•ฯ€ฮฑฮฝฮฑฯ†ฮฟฯฮฌ"; +"action_reset_identity" = "ฮ•ฯ€ฮฑฮฝฮฑฯ†ฮฟฯฮฌ ฯ„ฮฑฯ…ฯ„ฯŒฯ„ฮทฯ„ฮฑฯ‚"; "action_retry" = "ฮ•ฯ€ฮฑฮฝฮฌฮปฮทฯˆฮท"; "action_retry_decryption" = "ฮ•ฯ€ฮฑฮฝฮฌฮปฮทฯˆฮท ฮฑฯ€ฮฟฮบฯฯ…ฯ€ฯ„ฮฟฮณฯฮฌฯ†ฮทฯƒฮทฯ‚"; "action_save" = "ฮ‘ฯ€ฮฟฮธฮฎฮบฮตฯ…ฯƒฮท"; @@ -99,10 +104,18 @@ "action_take_photo" = "ฮคฯฮฌฮฒฮทฮพฮต ฯ†ฯ‰ฯ„ฮฟฮณฯฮฑฯ†ฮฏฮฑ"; "action_tap_for_options" = "ฮ ฮฌฯ„ฮฑ ฮณฮนฮฑ ฮตฯ€ฮนฮปฮฟฮณฮญฯ‚"; "action_try_again" = "ฮ ฯฮฟฯƒฯ€ฮฌฮธฮทฯƒฮต ฮพฮฑฮฝฮฌ"; +"action_unpin" = "ฮžฮตฮบฮฑฯฯ†ฮฏฯ„ฯƒฯ‰ฮผฮฑ"; +"action_view_in_timeline" = "ฮ ฯฮฟฮฒฮฟฮปฮฎ ฯƒฯ„ฮฟ ฯ‡ฯฮฟฮฝฮฟฮดฮนฮฌฮณฯฮฑฮผฮผฮฑ"; "action_view_source" = "ฮ ฯฮฟฮฒฮฟฮปฮฎ ฯ€ฮทฮณฮฎฯ‚"; "action_yes" = "ฮฮฑฮน"; "action.load_more" = "ฮฆฯŒฯฯ„ฯ‰ฯƒฮต ฯ€ฮตฯฮนฯƒฯƒฯŒฯ„ฮตฯฮฑ"; -"action.pin" = "ฮšฮฑฯฯ†ฮฏฯ„ฯƒฯ‰ฮผฮฑ"; +"action_deactivate_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" = "ฮกฯ…ฮธฮผฮฏฯƒฮตฮนฯ‚ ฮณฮนฮฑ ฯ€ฯฮฟฯ‡ฯ‰ฯฮทฮผฮญฮฝฮฟฯ…ฯ‚"; @@ -214,6 +227,7 @@ "common_waiting_for_decryption_key" = "ฮ‘ฮฝฮฑฮผฮฟฮฝฮฎ ฮณฮนฮฑ ฮฑฯ…ฯ„ฯŒ ฯ„ฮฟ ฮผฮฎฮฝฯ…ฮผฮฑ"; "common.do_not_show_this_again" = "ฮฮฑ ฮผฮทฮฝ ฮตฮผฯ†ฮฑฮฝฮนฯƒฯ„ฮตฮฏ ฮพฮฑฮฝฮฌ"; "common.open_source_licenses" = "ฮ†ฮดฮตฮนฮตฯ‚ ฮฑฮฝฮฟฮนฯ‡ฯ„ฮฟฯ ฮบฯŽฮดฮนฮบฮฑ"; +"common.pinned" = "ฮšฮฑฯฯ†ฮนฯ„ฯƒฯ‰ฮผฮญฮฝฮฟ"; "common.send_to" = "ฮ‘ฯ€ฮฟฯƒฯ„ฮฟฮปฮฎ ฯƒฮต"; "common_no_room_name" = "ฮงฯ‰ฯฮฏฯ‚ ฯŒฮฝฮฟฮผฮฑ ฮดฯ‰ฮผฮฑฯ„ฮฏฮฟฯ…"; "common_poll_end_confirmation" = "ฮ˜ฮตฯ‚ ฯƒฮฏฮณฮฟฯ…ฯฮฑ ฮฝฮฑ ฯ„ฮตฯฮผฮฑฯ„ฮฏฯƒฮตฮนฯ‚ ฮฑฯ…ฯ„ฮฎ ฯ„ฮท ฮดฮทฮผฮฟฯƒฮบฯŒฯ€ฮทฯƒฮท;"; @@ -244,6 +258,7 @@ "emoji_picker_category_people" = "ฮฆฮฑฯ„ฯƒฮฟฯฮปฮตฯ‚ & ฮ†ฮฝฮธฯฯ‰ฯ€ฮฟฮน"; "emoji_picker_category_places" = "ฮคฮฑฮพฮฏฮดฮนฮฑ & ฮœฮญฯฮท"; "emoji_picker_category_symbols" = "ฮฃฯฮผฮฒฮฟฮปฮฑ"; +"error_account_creation_not_possible" = "ฮŸ ฮฟฮนฮบฮนฮฑฮบฯŒฯ‚ ฮดฮนฮฑฮบฮฟฮผฮนฯƒฯ„ฮฎฯ‚ ฯƒฮฟฯ… ฯ€ฯฮญฯ€ฮตฮน ฮฝฮฑ ฮฑฮฝฮฑฮฒฮฑฮธฮผฮนฯƒฯ„ฮตฮฏ ฮณฮนฮฑ ฮฝฮฑ ฯ…ฯ€ฮฟฯƒฯ„ฮทฯฮฏฮถฮตฮน ฯ„ฮฟ Matrix Authentication Service ฮบฮฑฮน ฯ„ฮท ฮดฮทฮผฮนฮฟฯ…ฯฮณฮฏฮฑ ฮปฮฟฮณฮฑฯฮนฮฑฯƒฮผฮฟฯ."; "error_failed_creating_the_permalink" = "ฮ‘ฯ€ฮฟฯ„ฯ…ฯ‡ฮฏฮฑ ฮดฮทฮผฮนฮฟฯ…ฯฮณฮฏฮฑฯ‚ ฯ„ฮฟฯ… ฮผฯŒฮฝฮนฮผฮฟฯ… ฯƒฯ…ฮฝฮดฮญฯƒฮผฮฟฯ…"; "error_failed_loading_map" = "%1$@ ฮดฮตฮฝ ฮฎฯ„ฮฑฮฝ ฮดฯ…ฮฝฮฑฯ„ฮฎ ฮท ฯ†ฯŒฯฯ„ฯ‰ฯƒฮท ฯ„ฮฟฯ… ฯ‡ฮฌฯฯ„ฮท. ฮ ฮฑฯฮฑฮบฮฑฮปฯŽ ฮดฮฟฮบฮฏฮผฮฑฯƒฮต ฮพฮฑฮฝฮฌ ฮฑฯฮณฯŒฯ„ฮตฯฮฑ."; "error_failed_loading_messages" = "ฮ‘ฯ€ฮฟฯ„ฯ…ฯ‡ฮฏฮฑ ฯ†ฯŒฯฯ„ฯ‰ฯƒฮทฯ‚ ฮผฮทฮฝฯ…ฮผฮฌฯ„ฯ‰ฮฝ"; @@ -254,6 +269,8 @@ "error_some_messages_have_not_been_sent" = "ฮŸฯฮนฯƒฮผฮญฮฝฮฑ ฮผฮทฮฝฯฮผฮฑฯ„ฮฑ ฮดฮตฮฝ ฮญฯ‡ฮฟฯ…ฮฝ ฯƒฯ„ฮฑฮปฮตฮฏ"; "error_unknown" = "ฮ›ฯ…ฯ€ฮฟฯฮผฮฑฯƒฯ„ฮต, ฯ€ฮฑฯฮฟฯ…ฯƒฮนฮฌฯƒฯ„ฮทฮบฮต ฯƒฯ†ฮฌฮปฮผฮฑ"; "event_shield_reason_authenticity_not_guaranteed" = "ฮ— ฮฑฯ…ฮธฮตฮฝฯ„ฮนฮบฯŒฯ„ฮทฯ„ฮฑ ฮฑฯ…ฯ„ฮฟฯ ฯ„ฮฟฯ… ฮบฯฯ…ฯ€ฯ„ฮฟฮณฯฮฑฯ†ฮทฮผฮญฮฝฮฟฯ… ฮผฮทฮฝฯฮผฮฑฯ„ฮฟฯ‚ ฮดฮตฮฝ ฮตฮฏฮฝฮฑฮน ฮตฮณฮณฯ…ฮทฮผฮญฮฝฮท ฯƒฮต ฮฑฯ…ฯ„ฮฎฮฝ ฯ„ฮท ฯƒฯ…ฯƒฮบฮตฯ…ฮฎ."; +"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" = "ฮšฯฯ…ฯ€ฯ„ฮฟฮณฯฮฑฯ†ฮทฮผฮญฮฝฮฟ ฮฑฯ€ฯŒ ฮผฮท ฮตฯ€ฮฑฮปฮทฮธฮตฯ…ฮผฮญฮฝฮฟ ฯ‡ฯฮฎฯƒฯ„ฮท."; @@ -275,11 +292,14 @@ "notification_inline_reply_failed" = "** ฮ‘ฯ€ฮฟฯ„ฯ…ฯ‡ฮฏฮฑ ฮฑฯ€ฮฟฯƒฯ„ฮฟฮปฮฎฯ‚ - ฯ€ฮฑฯฮฑฮบฮฑฮปฯŽ ฮฌฮฝฮฟฮนฮพฮต ฯ„ฮฟ ฮดฯ‰ฮผฮฌฯ„ฮนฮฟ"; "notification_invitation_action_reject" = "ฮ‘ฯ€ฯŒฯฯฮนฯˆฮท"; "notification_invite_body" = "ฮฃฮต ฯ€ฯฮฟฯƒฮบฮฌฮปฮตฯƒฮต ฮฝฮฑ ฯƒฯ…ฮฝฮฟฮผฮนฮปฮฎฯƒฮตฯ„ฮต"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "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_sender_me" = "ฮ•ฮณฯŽ"; +"notification_sender_mention_reply" = "ฮŸ ฯ‡ฯฮฎฯƒฯ„ฮทฯ‚ %1$@ ฮฑฮฝฮฑฯ†ฮญฯฮธฮทฮบฮต ฮฎ ฮฑฯ€ฮฌฮฝฯ„ฮทฯƒฮต"; "notification_test_push_notification_content" = "ฮ’ฮปฮญฯ€ฮตฮนฯ‚ ฯ„ฮทฮฝ ฮตฮนฮดฮฟฯ€ฮฟฮฏฮทฯƒฮท! ฮšฮฌฮฝฮต ฮผฮฟฯ… ฮบฮปฮนฮบ!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -312,10 +332,27 @@ "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_pinned_timeline_empty_state_description" = "ฮ ฮฌฯ„ฮฑ ฯƒฮต ฮญฮฝฮฑ ฮผฮฎฮฝฯ…ฮผฮฑ ฮบฮฑฮน ฮตฯ€ฮญฮปฮตฮพฮต ยซ%1$@ยป ฮณฮนฮฑ ฮฝฮฑ ฯƒฯ…ฮผฯ€ฮตฯฮนฮปฮทฯ†ฮธฮตฮฏ ฮตฮดฯŽ."; +"screen_pinned_timeline_empty_state_headline" = "ฮšฮฑฯฯ†ฮฏฯ„ฯƒฯ‰ฯƒฮต ฯƒฮทฮผฮฑฮฝฯ„ฮนฮบฮฌ ฮผฮทฮฝฯฮผฮฑฯ„ฮฑ, ฯŽฯƒฯ„ฮต ฮฝฮฑ ฮผฯ€ฮฟฯฮฟฯฮฝ ฮฝฮฑ ฮตฮฝฯ„ฮฟฯ€ฮนฯƒฯ„ฮฟฯฮฝ ฮตฯฮบฮฟฮปฮฑ"; +"screen_pinned_timeline_screen_title_empty" = "ฮšฮฑฯฯ†ฮนฯ„ฯƒฯ‰ฮผฮญฮฝฮฑ ฮผฮทฮฝฯฮผฮฑฯ„ฮฑ"; +"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.pinned_banner_indicator" = "%1$@ ฮฑฯ€ฯŒ %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ ฮšฮฑฯฯ†ฮนฯ„ฯƒฯ‰ฮผฮญฮฝฮฑ ฮผฮทฮฝฯฮผฮฑฯ„ฮฑ"; -"screen.room.pinned_banner_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_details_pinned_events_row_title" = "ฮšฮฑฯฯ†ฮนฯ„ฯƒฯ‰ฮผฮญฮฝฮฑ ฮผฮทฮฝฯฮผฮฑฯ„ฮฑ"; +"screen_timeline_item_menu_send_failure_changed_identity" = "ฮคฮฟ ฮผฮฎฮฝฯ…ฮผฮฑ ฮดฮตฮฝ ฯƒฯ„ฮฌฮปฮธฮทฮบฮต ฮตฯ€ฮตฮนฮดฮฎ ฮท ฮตฯ€ฮฑฮปฮทฮธฮตฯ…ฮผฮญฮฝฮท ฯ„ฮฑฯ…ฯ„ฯŒฯ„ฮทฯ„ฮฑ ฯ„ฮฟฯ… ฯ‡ฯฮฎฯƒฯ„ฮท %1$@ ฮญฯ‡ฮตฮน ฮฑฮปฮปฮฌฮพฮตฮน."; +"screen_timeline_item_menu_send_failure_unsigned_device" = "ฮคฮฟ ฮผฮฎฮฝฯ…ฮผฮฑ ฮดฮตฮฝ ฯƒฯ„ฮฌฮปฮธฮทฮบฮต ฮตฯ€ฮตฮนฮดฮฎ ฮฟ ฯ‡ฯฮฎฯƒฯ„ฮทฯ‚ %1$@ ฮดฮตฮฝ ฮญฯ‡ฮตฮน ฮตฯ€ฮฑฮปฮทฮธฮตฯฯƒฮตฮน ฯŒฮปฮตฯ‚ ฯ„ฮนฯ‚ ฯƒฯ…ฯƒฮบฮตฯ…ฮญฯ‚."; +"screen_timeline_item_menu_send_failure_you_unsigned_device" = "ฮคฮฟ ฮผฮฎฮฝฯ…ฮผฮฑ ฮดฮตฮฝ ฯƒฯ„ฮฌฮปฮธฮทฮบฮต ฮตฯ€ฮตฮนฮดฮฎ ฮดฮตฮฝ ฮญฯ‡ฮตฮนฯ‚ ฮตฯ€ฮฑฮปฮทฮธฮตฯฯƒฮตฮน ฯ„ฮฟฯ…ฮปฮฌฯ‡ฮนฯƒฯ„ฮฟฮฝ ฮผฮฏฮฑ ฮฑฯ€ฯŒ ฯ„ฮนฯ‚ ฯƒฯ…ฯƒฮบฮตฯ…ฮญฯ‚ ฯƒฮฟฯ…."; "screen_account_provider_change" = "ฮ‘ฮปฮปฮฑฮณฮฎ ฯ€ฮฑฯฯŒฯ‡ฮฟฯ… ฮปฮฟฮณฮฑฯฮนฮฑฯƒฮผฮฟฯ"; "screen_account_provider_form_hint" = "ฮ”ฮนฮตฯฮธฯ…ฮฝฯƒฮท ฮฟฮนฮบฮนฮฑฮบฮฟฯ ฮดฮนฮฑฮบฮฟฮผฮนฯƒฯ„ฮฎ"; "screen_account_provider_form_notice" = "ฮ•ฮนฯƒฮฎฮณฮฑฮณฮต ฮญฮฝฮฑฮฝ ฯŒฯฮฟ ฮฑฮฝฮฑฮถฮฎฯ„ฮทฯƒฮทฯ‚ ฮฎ ฮผฮนฮฑ ฮดฮนฮตฯฮธฯ…ฮฝฯƒฮท ฯ„ฮฟฮผฮญฮฑ."; @@ -398,6 +435,7 @@ "screen_chat_backup_recovery_action_confirm_description" = "ฮคฮฟ ฮฑฮฝฯ„ฮฏฮณฯฮฑฯ†ฮฟ ฮฑฯƒฯ†ฮฑฮปฮตฮฏฮฑฯ‚ ฯ„ฮทฯ‚ ฯƒฯ…ฮฝฮฟฮผฮนฮปฮฏฮฑฯ‚ ฯƒฮฟฯ… ฮดฮตฮฝ ฮตฮฏฮฝฮฑฮน ฯƒฯ…ฮณฯ‡ฯฮฟฮฝฮนฯƒฮผฮญฮฝฮฟ ฮฑฯ…ฯ„ฮฎฮฝ ฯ„ฮท ฯƒฯ„ฮนฮณฮผฮฎ."; "screen_chat_backup_recovery_action_setup" = "ฮกฯฮธฮผฮนฯƒฮท ฮฑฮฝฮฌฮบฯ„ฮทฯƒฮทฯ‚"; "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$@"; @@ -421,6 +459,17 @@ "screen_create_room_public_option_description" = "ฮคฮฑ ฮผฮทฮฝฯฮผฮฑฯ„ฮฑ ฮดฮตฮฝ ฮตฮฏฮฝฮฑฮน ฮบฯฯ…ฯ€ฯ„ฮฟฮณฯฮฑฯ†ฮทฮผฮญฮฝฮฑ ฮบฮฑฮน ฮฟ ฮบฮฑฮธฮญฮฝฮฑฯ‚ ฮผฯ€ฮฟฯฮตฮฏ ฮฝฮฑ ฯ„ฮฑ ฮดฮนฮฑฮฒฮฌฯƒฮตฮน. ฮœฯ€ฮฟฯฮตฮฏฯ‚ ฮฝฮฑ ฮตฮฝฮตฯฮณฮฟฯ€ฮฟฮนฮฎฯƒฮตฮนฯ‚ ฯ„ฮทฮฝ ฮบฯฯ…ฯ€ฯ„ฮฟฮณฯฮฌฯ†ฮทฯƒฮท ฮฑฯฮณฯŒฯ„ฮตฯฮฑ."; "screen_create_room_public_option_title" = "ฮ”ฮทฮผฯŒฯƒฮนฮฟ ฮดฯ‰ฮผฮฌฯ„ฮนฮฟ (ฮฟฯ€ฮฟฮนฮฟฯƒฮดฮฎฯ€ฮฟฯ„ฮต)"; "screen_create_room_topic_label" = "ฮ˜ฮญฮผฮฑ (ฯ€ฯฮฟฮฑฮนฯฮตฯ„ฮนฮบฯŒ)"; +"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" = "ฮคฮฟ ฮตฮผฯ†ฮฑฮฝฮนฮถฯŒฮผฮตฮฝฮฟ ฯŒฮฝฮฟฮผฮฌ ฯƒฮฟฯ…"; @@ -428,12 +477,20 @@ "screen_edit_profile_error_title" = "ฮ”ฮตฮฝ ฮตฮฏฮฝฮฑฮน ฮดฯ…ฮฝฮฑฯ„ฮฎ ฮท ฮตฮฝฮทฮผฮญฯฯ‰ฯƒฮท ฯ„ฮฟฯ… ฯ€ฯฮฟฯ†ฮฏฮป"; "screen_edit_profile_title" = "ฮ•ฯ€ฮตฮพฮตฯฮณฮฑฯƒฮฏฮฑ ฯ€ฯฮฟฯ†ฮฏฮป"; "screen_edit_profile_updating_details" = "ฮ•ฮฝฮทฮผฮญฯฯ‰ฯƒฮท ฯ€ฯฮฟฯ†ฮฏฮป..."; +"screen_encryption_reset_action_continue_reset" = "ฮฃฯ…ฮฝฮญฯ‡ฮนฯƒฮท ฮตฯ€ฮฑฮฝฮฑฯ†ฮฟฯฮฌฯ‚"; +"screen_encryption_reset_bullet_1" = "ฮคฮฑ ฯƒฯ„ฮฟฮนฯ‡ฮตฮฏฮฑ ฯ„ฮฟฯ… ฮปฮฟฮณฮฑฯฮนฮฑฯƒฮผฮฟฯ ฯƒฮฟฯ…, ฮฟฮน ฮตฯ€ฮฑฯ†ฮญฯ‚, ฮฟฮน ฯ€ฯฮฟฯ„ฮนฮผฮฎฯƒฮตฮนฯ‚ ฮบฮฑฮน ฮท ฮปฮฏฯƒฯ„ฮฑ ฯƒฯ…ฮฝฮฟฮผฮนฮปฮนฯŽฮฝ ฮธฮฑ ฮดฮนฮฑฯ„ฮทฯฮทฮธฮฟฯฮฝ"; +"screen_encryption_reset_bullet_2" = "ฮ˜ฮฑ ฯ‡ฮฌฯƒฮตฮนฯ‚ ฯ„ฮฟ ฯ…ฯ€ฮฌฯฯ‡ฮฟฮฝ ฮนฯƒฯ„ฮฟฯฮนฮบฯŒ ฮผฮทฮฝฯ…ฮผฮฌฯ„ฯ‰ฮฝ ฯƒฮฟฯ…"; +"screen_encryption_reset_bullet_3" = "ฮ˜ฮฑ ฯ‡ฯฮตฮนฮฑฯƒฯ„ฮตฮฏ ฮฝฮฑ ฮตฯ€ฮฑฮปฮทฮธฮตฯฯƒฮตฮนฯ‚ ฮพฮฑฮฝฮฌ ฯŒฮปฮตฯ‚ ฯ„ฮนฯ‚ ฯ…ฯ€ฮฌฯฯ‡ฮฟฯ…ฯƒฮตฯ‚ ฯƒฯ…ฯƒฮบฮตฯ…ฮญฯ‚ ฮบฮฑฮน ฮตฯ€ฮฑฯ†ฮญฯ‚ ฯƒฮฟฯ…"; +"screen_encryption_reset_footer" = "ฮ•ฯ€ฮฑฮฝฮฌฯ†ฮตฯฮต ฯ„ฮทฮฝ ฯ„ฮฑฯ…ฯ„ฯŒฯ„ฮทฯ„ฮฌ ฯƒฮฟฯ… ฮผฯŒฮฝฮฟ ฮตฮฌฮฝ ฮดฮตฮฝ ฮญฯ‡ฮตฮนฯ‚ ฯ€ฯฯŒฯƒฮฒฮฑฯƒฮท ฯƒฮต ฮฌฮปฮปฮท ฯƒฯ…ฮฝฮดฮตฮดฮตฮผฮญฮฝฮท ฯƒฯ…ฯƒฮบฮตฯ…ฮฎ ฮบฮฑฮน ฮญฯ‡ฮตฮนฯ‚ ฯ‡ฮฌฯƒฮตฮน ฯ„ฮฟ ฮบฮปฮตฮนฮดฮฏ ฮฑฮฝฮฌฮบฯ„ฮทฯƒฮทฯ‚."; +"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" = "ฮงฯฮฎฯƒฮท ฮฌฮปฮปฮทฯ‚ ฯƒฯ…ฯƒฮบฮตฯ…ฮฎฯ‚"; +"screen_identity_confirmation_use_recovery_key" = "ฮงฯฮฎฯƒฮท ฮบฮปฮตฮนฮดฮนฮฟฯ ฮฑฮฝฮฌฮบฯ„ฮทฯƒฮทฯ‚"; "screen_identity_confirmed_subtitle" = "ฮคฯŽฯฮฑ ฮผฯ€ฮฟฯฮตฮฏฯ‚ ฮฝฮฑ ฮดฮนฮฑฮฒฮฌฮถฮตฮนฯ‚ ฮฎ ฮฝฮฑ ฯƒฯ„ฮญฮปฮฝฮตฮนฯ‚ ฮผฮทฮฝฯฮผฮฑฯ„ฮฑ ฮผฮต ฮฑฯƒฯ†ฮฌฮปฮตฮนฮฑ ฮบฮฑฮน ฮตฯ€ฮฏฯƒฮทฯ‚ ฮผฯ€ฮฟฯฮตฮฏ ฮฝฮฑ ฮตฮผฯ€ฮนฯƒฯ„ฮตฯ…ฯ„ฮตฮฏ ฮฑฯ…ฯ„ฮฎฮฝ ฯ„ฮท ฯƒฯ…ฯƒฮบฮตฯ…ฮฎ ฮฟฯ€ฮฟฮนฮฟฯƒฮดฮฎฯ€ฮฟฯ„ฮต ฮผฮต ฯ„ฮฟฮฝ ฮฟฯ€ฮฟฮฏฮฟ ฯƒฯ…ฮฝฮฟฮผฮนฮปฮตฮฏฯ‚."; "screen_identity_confirmed_title" = "ฮ•ฯ€ฮฑฮปฮทฮธฮตฯ…ฮผฮญฮฝฮท ฯƒฯ…ฯƒฮบฮตฯ…ฮฎ"; -"screen_identity_use_another_device" = "ฮงฯฮฎฯƒฮท ฮฌฮปฮปฮทฯ‚ ฯƒฯ…ฯƒฮบฮตฯ…ฮฎฯ‚"; "screen_identity_waiting_on_other_device" = "ฮ‘ฮฝฮฑฮผฮฟฮฝฮฎ ฯƒฮต ฮฌฮปฮปฮท ฯƒฯ…ฯƒฮบฮตฯ…ฮฎ..."; "screen_invites_decline_chat_message" = "ฮฃฮฏฮณฮฟฯ…ฯฮฑ ฮธฮตฯ‚ ฮฝฮฑ ฮฑฯ€ฮฟฯฯฮฏฯˆฮตฮนฯ‚ ฯ„ฮทฮฝ ฯ€ฯฯŒฯƒฮบฮปฮทฯƒฮท ฯƒฯ…ฮผฮผฮตฯ„ฮฟฯ‡ฮฎฯ‚ ฯƒฯ„ฮฟ %1$@;"; "screen_invites_decline_chat_title" = "ฮ‘ฯ€ฯŒฯฯฮนฯˆฮท ฯ€ฯฯŒฯƒฮบฮปฮทฯƒฮทฯ‚"; @@ -556,7 +613,6 @@ "screen_recovery_key_confirm_error_content" = "ฮ ฯฮฟฯƒฯ€ฮฌฮธฮทฯƒฮต ฮพฮฑฮฝฮฌ ฮณฮนฮฑ ฮฝฮฑ ฮตฯ€ฮนฮฒฮตฮฒฮฑฮนฯŽฯƒฮตฮนฯ‚ ฯ„ฮทฮฝ ฯ€ฯฯŒฯƒฮฒฮฑฯƒฮท ฯƒฯ„ฮฟ ฮฑฮฝฯ„ฮฏฮณฯฮฑฯ†ฮฟ ฮฑฯƒฯ†ฮฑฮปฮตฮฏฮฑฯ‚ ฯ„ฮทฯ‚ ฯƒฯ…ฮฝฮฟฮผฮนฮปฮฏฮฑฯ‚ ฯƒฮฟฯ…."; "screen_recovery_key_confirm_error_title" = "ฮ›ฮฑฮฝฮธฮฑฯƒฮผฮญฮฝฮฟ ฮบฮปฮตฮนฮดฮฏ ฮฑฮฝฮฌฮบฯ„ฮทฯƒฮทฯ‚"; "screen_recovery_key_confirm_key_description" = "ฮ•ฮฌฮฝ ฮญฯ‡ฮตฮนฯ‚ ฮญฮฝฮฑ ฮบฮปฮตฮนฮดฮฏ ฮฑฯƒฯ†ฮฑฮปฮตฮฏฮฑฯ‚ ฮฎ ฮผฮนฮฑ ฯ†ฯฮฌฯƒฮท ฮฑฯƒฯ†ฮฑฮปฮตฮฏฮฑฯ‚, ฮธฮฑ ฮปฮตฮนฯ„ฮฟฯ…ฯฮณฮฎฯƒฮตฮน ฮตฯ€ฮฏฯƒฮทฯ‚."; -"screen_recovery_key_confirm_key_label" = "ฮšฮปฮตฮนฮดฮฏ ฮฑฮฝฮฌฮบฯ„ฮทฯƒฮทฯ‚ ฮฎ ฮบฯ‰ฮดฮนฮบฯŒฯ‚ ฯ€ฯฯŒฯƒฮฒฮฑฯƒฮทฯ‚"; "screen_recovery_key_confirm_key_placeholder" = "ฮ•ฮนฯƒฮฑฮณฯ‰ฮณฮฎ..."; "screen_recovery_key_confirm_lost_recovery_key" = "ฮˆฯ‡ฮฑฯƒฮตฯ‚ ฯ„ฮฟ ฮบฮปฮตฮนฮดฮฏ ฮฑฮฝฮฌฮบฯ„ฮทฯƒฮทฯ‚;"; "screen_recovery_key_confirm_success" = "ฮ•ฯ€ฮนฮฒฮตฮฒฮฑฮนฯŽฮธฮทฮบฮต ฯ„ฮฟ ฮบฮปฮตฮนฮดฮฏ ฮฑฮฝฮฌฮบฯ„ฮทฯƒฮทฯ‚"; @@ -577,6 +633,14 @@ "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_placeholder" = "ฮ•ฮนฯƒฮฑฮณฯ‰ฮณฮฎ..."; +"screen_reset_encryption_password_subtitle" = "ฮ•ฯ€ฮนฮฒฮตฮฒฮฑฮฏฯ‰ฯƒฮต ฯŒฯ„ฮน ฮธฮตฯ‚ ฮฝฮฑ ฮตฯ€ฮฑฮฝฮฑฯ†ฮญฯฮตฮนฯ‚ ฯ„ฮทฮฝ ฯ„ฮฑฯ…ฯ„ฯŒฯ„ฮทฯ„ฮฌ ฯƒฮฟฯ…."; +"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_attachment_source_camera" = "ฮšฮฌฮผฮตฯฮฑ"; "screen_room_attachment_source_camera_video" = "ฮ•ฮณฮณฯฮฑฯ†ฮฎ ฮฒฮฏฮฝฯ„ฮตฮฟ"; @@ -644,7 +708,7 @@ "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_banning_user" = "ฮ‘ฯ€ฮฟฮบฮปฮตฮนฯƒฮผฯŒฯ‚ ฯ„ฮฟฯ… ฯ‡ฯฮฎฯƒฯ„ฮท %1$@"; +"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_ban" = "ฮ‘ฯ†ฮฑฮฏฯฮตฯƒฮท ฮบฮฑฮน ฮฑฯ€ฮฟฮบฮปฮตฮนฯƒฮผฯŒฯ‚ ฮผฮญฮปฮฟฯ…ฯ‚"; @@ -775,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "ฮˆฯ‡ฮตฮนฯ‚ ฮฑฯ€ฮฟฮธฮทฮบฮตฯฯƒฮตฮน ฯ„ฮฟ ฮบฮปฮตฮนฮดฮฏ ฮฑฮฝฮฌฮบฯ„ฮทฯƒฮทฯ‚;"; "screen_start_chat_error_starting_chat" = "ฮ ฮฑฯฮฟฯ…ฯƒฮนฮฌฯƒฯ„ฮทฮบฮต ฯƒฯ†ฮฌฮปฮผฮฑ ฮบฮฑฯ„ฮฌ ฯ„ฮทฮฝ ฯ€ฯฮฟฯƒฯ€ฮฌฮธฮตฮนฮฑ ฮญฮฝฮฑฯฮพฮทฯ‚ ฮผฮนฮฑฯ‚ ฯƒฯ…ฮฝฮฟฮผฮนฮปฮฏฮฑฯ‚"; "screen_view_location_title" = "ฮคฮฟฯ€ฮฟฮธฮตฯƒฮฏฮฑ"; -"screen_waitlist_message" = "ฮฅฯ€ฮฌฯฯ‡ฮตฮน ฮผฮตฮณฮฌฮปฮท ฮถฮฎฯ„ฮทฯƒฮท ฮณฮนฮฑ ฯ„ฮฟ %1$@ ฯƒฯ„ฮฟฮฝ %2$@ ฮฑฯ…ฯ„ฮฎ ฯ„ฮท ฯƒฯ„ฮนฮณฮผฮฎ. ฮ•ฯ€ฮญฯƒฯ„ฯฮตฯˆฮต ฯƒฯ„ฮทฮฝ ฮตฯ†ฮฑฯฮผฮฟฮณฮฎ ฯƒฮต ฮปฮฏฮณฮตฯ‚ ฮผฮญฯฮตฯ‚ ฮบฮฑฮน ฮดฮฟฮบฮฏฮผฮฑฯƒฮต ฮพฮฑฮฝฮฌ.\n\nฮ•ฯ…ฯ‡ฮฑฯฮนฯƒฯ„ฯŽ ฮณฮนฮฑ ฯ„ฮทฮฝ ฯ…ฯ€ฮฟฮผฮฟฮฝฮฎ ฯƒฮฟฯ…!"; -"screen_waitlist_title" = "ฮฃฯ‡ฮตฮดฯŒฮฝ ฯ„ฮฑ ฮบฮฑฯ„ฮฌฯ†ฮตฯฮตฯ‚."; -"screen_waitlist_title_success" = "ฮ•ฮฏฯƒฮฑฮน ฮผฮญฯƒฮฑ."; "screen_welcome_bullet_1" = "ฮšฮปฮฎฯƒฮตฮนฯ‚, ฮดฮทฮผฮฟฯƒฮบฮฟฯ€ฮฎฯƒฮตฮนฯ‚, ฮฑฮฝฮฑฮถฮฎฯ„ฮทฯƒฮท ฮบฮฑฮน ฮฌฮปฮปฮฑ, ฮธฮฑ ฯ€ฯฮฟฯƒฯ„ฮตฮธฮฟฯฮฝ ฮฑฯฮณฯŒฯ„ฮตฯฮฑ ฯ†ฮญฯ„ฮฟฯ‚."; "screen_welcome_bullet_2" = "ฮคฮฟ ฮนฯƒฯ„ฮฟฯฮนฮบฯŒ ฮผฮทฮฝฯ…ฮผฮฌฯ„ฯ‰ฮฝ ฮณฮนฮฑ ฮบฯฯ…ฯ€ฯ„ฮฟฮณฯฮฑฯ†ฮทฮผฮญฮฝฮฑ ฮดฯ‰ฮผฮฌฯ„ฮนฮฑ ฮดฮตฮฝ ฮตฮฏฮฝฮฑฮน ฮฑฮบฯŒฮผฮฑ ฮดฮนฮฑฮธฮญฯƒฮนฮผฮฟ."; "screen_welcome_bullet_3" = "ฮ˜ฮฑ ฮธฮญฮปฮฑฮผฮต ฮฝฮฑ ฮฑฮบฮฟฯฯƒฮฟฯ…ฮผฮต ฯ„ฮท ฮณฮฝฯŽฮผฮท ฯƒฮฟฯ…, ฯ€ฮตฯ‚ ฮผฮฑฯ‚ ฯ„ฮท ฮณฮฝฯŽฮผฮท ฯƒฮฟฯ… ฮผฮญฯƒฯ‰ ฯ„ฮทฯ‚ ฯƒฮตฮปฮฏฮดฮฑฯ‚ ฯฯ…ฮธฮผฮฏฯƒฮตฯ‰ฮฝ."; @@ -834,6 +895,12 @@ "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$@ ฮฌฮปฮปฮฑฮพฮต ฯ„ฮฑ ฮบฮฑฯฯ†ฮนฯ„ฯƒฯ‰ฮผฮญฮฝฮฑ ฮผฮทฮฝฯฮผฮฑฯ„ฮฑ"; +"state_event_room_pinned_events_changed_by_you" = "ฮ†ฮปฮปฮฑฮพฮตฯ‚ ฯ„ฮฑ ฮบฮฑฯฯ†ฮนฯ„ฯƒฯ‰ฮผฮญฮฝฮฑ ฮผฮทฮฝฯฮผฮฑฯ„ฮฑ"; +"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_by_you" = "ฮžฮตฮบฮฑฯฯ†ฮฏฯ„ฯƒฯ‰ฯƒฮตฯ‚ ฮญฮฝฮฑ ฮผฮฎฮฝฯ…ฮผฮฑ"; "state_event_room_reject" = "ฮŸ ฯ‡ฯฮฎฯƒฯ„ฮทฯ‚ %1$@ ฮฑฯ€ฮญฯฯฮนฯˆฮต ฯ„ฮทฮฝ ฯ€ฯฯŒฯƒฮบฮปฮทฯƒฮท"; "state_event_room_reject_by_you" = "ฮ‘ฯ€ฮญฯฯฮนฯˆฮตฯ‚ ฯ„ฮทฮฝ ฯ€ฯฯŒฯƒฮบฮปฮทฯƒฮท"; "state_event_room_remove" = "ฮŸ ฯ‡ฯฮฎฯƒฯ„ฮทฯ‚ %1$@ ฮฑฯ†ฮฑฮฏฯฮตฯƒฮต ฯ„ฮฟฮฝ ฯ‡ฯฮฎฯƒฯ„ฮท %2$@"; @@ -921,6 +988,7 @@ "screen_dm_details_unblock_user" = "ฮšฮฑฯ„ฮฌฯฮณฮทฯƒฮท ฮฑฯ€ฮฟฮบฮปฮตฮนฯƒฮผฮฟฯ ฯ‡ฯฮฎฯƒฯ„ฮท"; "screen_edit_poll_delete_confirmation_title" = "ฮ”ฮนฮฑฮณฯฮฑฯ†ฮฎ ฮ”ฮทฮผฮฟฯƒฮบฯŒฯ€ฮทฯƒฮทฯ‚"; "screen_edit_poll_title" = "ฮ•ฯ€ฮตฮพฮตฯฮณฮฑฯƒฮฏฮฑ ฮดฮทฮผฮฟฯƒฮบฯŒฯ€ฮทฯƒฮทฯ‚"; +"screen_identity_use_another_device" = "ฮงฯฮฎฯƒฮท ฮฌฮปฮปฮทฯ‚ ฯƒฯ…ฯƒฮบฮตฯ…ฮฎฯ‚"; "screen_login_subtitle" = "ฮคฮฟ Matrix ฮตฮฏฮฝฮฑฮน ฮญฮฝฮฑ ฮฑฮฝฮฟฮนฯ‡ฯ„ฯŒ ฮดฮฏฮบฯ„ฯ…ฮฟ ฮณฮนฮฑ ฮฑฯƒฯ†ฮฑฮปฮฎ, ฮฑฯ€ฮฟฮบฮตฮฝฯ„ฯฯ‰ฮผฮญฮฝฮท ฮตฯ€ฮนฮบฮฟฮนฮฝฯ‰ฮฝฮฏฮฑ."; "screen_qr_code_login_invalid_scan_state_retry_button" = "ฮ ฯฮฟฯƒฯ€ฮฌฮธฮทฯƒฮต ฮพฮฑฮฝฮฌ"; "screen_report_content_block_user" = "ฮ‘ฯ€ฮฟฮบฮปฮตฮนฯƒฮผฯŒฯ‚ ฯ‡ฯฮฎฯƒฯ„ฮท"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "ฮ‘ฯ€ฮฟฯƒฯฮฝฮดฮตฯƒฮท"; "screen_signout_confirmation_dialog_title" = "ฮ‘ฯ€ฮฟฯƒฯฮฝฮดฮตฯƒฮท"; "screen_signout_preference_item" = "ฮ‘ฯ€ฮฟฯƒฯฮฝฮดฮตฯƒฮท"; -"screen_waitlist_message_success" = "ฮšฮฑฮปฯŽฯ‚ ฮฎฯฮธฮตฯ‚ ฯƒฯ„ฮฟ %1$@!"; diff --git a/ElementX/Resources/Localizations/el.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/el.lproj/Localizable.stringsdict index e1f3a90b92..d17d98a85e 100644 --- a/ElementX/Resources/Localizations/el.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/el.lproj/Localizable.stringsdict @@ -194,6 +194,22 @@ ฮ›ฮฌฮธฮฟฯ‚ PIN. ฮˆฯ‡ฮตฮนฯ‚ %1$d ฮฑฮบฯŒฮผฮท ฮตฯ…ฮบฮฑฮนฯฮฏฮตฯ‚ + screen_pinned_timeline_screen_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d ฮšฮฑฯฯ†ฮนฯ„ฯƒฯ‰ฮผฮญฮฝฮฟ ฮผฮฎฮฝฯ…ฮผฮฑ + other + %1$d ฮšฮฑฯฯ†ฮนฯ„ฯƒฯ‰ฮผฮญฮฝฮฑ ฮผฮทฮฝฯฮผฮฑฯ„ฮฑ + + screen_room_member_list_header_title NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index e73aff3a65..ad6dae5baa 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -27,17 +27,20 @@ "action_back" = "Back"; "action_call" = "Call"; "action_cancel" = "Cancel"; +"action_cancel_for_now" = "Cancel for now"; "action_choose_photo" = "Choose photo"; "action_clear" = "Clear"; "action_close" = "Close"; "action_complete_verification" = "Complete verification"; "action_confirm" = "Confirm"; +"action_confirm_password" = "Confirm password"; "action_continue" = "Continue"; "action_copy" = "Copy"; "action_copy_link" = "Copy link"; "action_copy_link_to_message" = "Copy link to message"; "action_create" = "Create"; "action_create_a_room" = "Create a room"; +"action_deactivate" = "Deactivate"; "action_decline" = "Decline"; "action_delete_poll" = "Delete Poll"; "action_disable" = "Disable"; @@ -102,9 +105,17 @@ "action_tap_for_options" = "Tap for options"; "action_try_again" = "Try again"; "action_unpin" = "Unpin"; +"action_view_in_timeline" = "View in timeline"; "action_view_source" = "View source"; "action_yes" = "Yes"; "action.load_more" = "Load more"; +"action_deactivate_account" = "Deactivate account"; +"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" = "Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices."; +"banner.set_up_recovery.title" = "Set up recovery"; "common_about" = "About"; "common_acceptable_use_policy" = "Acceptable use policy"; "common_advanced_settings" = "Advanced settings"; @@ -216,6 +227,7 @@ "common_waiting_for_decryption_key" = "Waiting for this message"; "common.do_not_show_this_again" = "Do not show this again"; "common.open_source_licenses" = "Open source licenses"; +"common.pinned" = "Pinned"; "common.send_to" = "Send to"; "common_no_room_name" = "No room name"; "common_poll_end_confirmation" = "Are you sure you want to end this poll?"; @@ -246,6 +258,7 @@ "emoji_picker_category_people" = "Smileys & People"; "emoji_picker_category_places" = "Travel & Places"; "emoji_picker_category_symbols" = "Symbols"; +"error_account_creation_not_possible" = "Your homeserver needs to be upgraded to support Matrix Authentication Service and account creation."; "error_failed_creating_the_permalink" = "Failed creating the permalink"; "error_failed_loading_map" = "%1$@ could not load the map. Please try again later."; "error_failed_loading_messages" = "Failed loading messages"; @@ -256,6 +269,7 @@ "error_some_messages_have_not_been_sent" = "Some messages have not been sent"; "error_unknown" = "Sorry, an error occurred"; "event_shield_reason_authenticity_not_guaranteed" = "The authenticity of this encrypted message can't be guaranteed on this device."; +"event_shield_reason_previously_verified" = "Encrypted by a previously-verified user."; "event_shield_reason_sent_in_clear" = "Not encrypted."; "event_shield_reason_unknown_device" = "Encrypted by an unknown or deleted device."; "event_shield_reason_unsigned_device" = "Encrypted by a device not verified by its owner."; @@ -278,11 +292,14 @@ "notification_inline_reply_failed" = "** Failed to send - please open room"; "notification_invitation_action_reject" = "Reject"; "notification_invite_body" = "Invited you to chat"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "notification_mentioned_you_body" = "Mentioned you: %1$@"; "notification_new_messages" = "New Messages"; "notification_reaction_body" = "Reacted with %1$@"; "notification_room_invite_body" = "Invited you to join the room"; +"notification_room_invite_body_with_sender" = "%1$@ invited you to join the room"; "notification_sender_me" = "Me"; +"notification_sender_mention_reply" = "%1$@ mentioned or replied"; "notification_test_push_notification_content" = "You are viewing the notification! Click me!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -318,12 +335,24 @@ "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_pinned_timeline_screen_title_empty" = "Pinned messages"; +"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" = "Notify the whole room"; "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_details_pinned_events_row_title" = "Pinned messages"; +"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_account_provider_change" = "Change account provider"; "screen_account_provider_form_hint" = "Homeserver address"; "screen_account_provider_form_notice" = "Enter a search term or a domain address."; @@ -406,6 +435,7 @@ "screen_chat_backup_recovery_action_confirm_description" = "Your chat backup is currently out of sync."; "screen_chat_backup_recovery_action_setup" = "Set up recovery"; "screen_chat_backup_recovery_action_setup_description" = "Get access to your encrypted messages if you lose all your devices or are signed out of %1$@ everywhere."; +"screen_create_account_title" = "Create account"; "screen_create_new_recovery_key_list_item_1" = "Open %1$@ in a desktop device"; "screen_create_new_recovery_key_list_item_2" = "Sign into your account again"; "screen_create_new_recovery_key_list_item_3" = "When asked to verify your device, select %1$@"; @@ -429,6 +459,17 @@ "screen_create_room_public_option_description" = "Messages are not encrypted and anyone can read them. You can enable encryption at a later date."; "screen_create_room_public_option_title" = "Public room (anyone)"; "screen_create_room_topic_label" = "Topic (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_edit_poll_delete_confirmation" = "Are you sure you want to delete this poll?"; "screen_edit_profile_display_name" = "Display name"; "screen_edit_profile_display_name_placeholder" = "Your display name"; @@ -436,16 +477,16 @@ "screen_edit_profile_error_title" = "Unable to update profile"; "screen_edit_profile_title" = "Edit profile"; "screen_edit_profile_updating_details" = "Updating profileโ€ฆ"; +"screen_encryption_reset_action_continue_reset" = "Continue reset"; "screen_encryption_reset_bullet_1" = "Your account details, contacts, preferences, and chat list will be kept"; "screen_encryption_reset_bullet_2" = "You will lose your existing message history"; "screen_encryption_reset_bullet_3" = "You will need to verify all your existing devices and contacts again"; "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_subtitle" = "If youโ€™re not signed in to any other devices and youโ€™ve lost your recovery key, then youโ€™ll need to reset your identity to continue using the app. "; -"screen_encryption_reset_title" = "Reset your identity in case you canโ€™t confirm another way"; +"screen_encryption_reset_title" = "Can't confirm? Youโ€™ll need to reset your identity."; "screen_identity_confirmation_cannot_confirm" = "Can't confirm?"; "screen_identity_confirmation_create_new_recovery_key" = "Create a new recovery key"; "screen_identity_confirmation_subtitle" = "Verify this device to set up secure messaging."; -"screen_identity_confirmation_title" = "Confirm that it's you"; +"screen_identity_confirmation_title" = "Confirm your identity"; "screen_identity_confirmation_use_another_device" = "Use another device"; "screen_identity_confirmation_use_recovery_key" = "Use recovery key"; "screen_identity_confirmed_subtitle" = "Now you can read or send messages securely, and anyone you chat with can also trust this device."; @@ -572,7 +613,6 @@ "screen_recovery_key_confirm_error_content" = "Please try again to confirm access to your chat backup."; "screen_recovery_key_confirm_error_title" = "Incorrect recovery key"; "screen_recovery_key_confirm_key_description" = "If you have a security key or security phrase, this will work too."; -"screen_recovery_key_confirm_key_label" = "Recovery key or passcode"; "screen_recovery_key_confirm_key_placeholder" = "Enterโ€ฆ"; "screen_recovery_key_confirm_lost_recovery_key" = "Lost your recovery key?"; "screen_recovery_key_confirm_success" = "Recovery key confirmed"; @@ -595,10 +635,12 @@ "screen_report_content_hint" = "Reason for reporting this content"; "screen_reset_encryption_confirmation_alert_action" = "Yes, reset now"; "screen_reset_encryption_confirmation_alert_subtitle" = "This process is irreversible."; -"screen_reset_encryption_confirmation_alert_title" = "Are you sure you want to reset your encryption?"; +"screen_reset_encryption_confirmation_alert_title" = "Are you sure you want to reset your identity?"; "screen_reset_encryption_password_placeholder" = "Enterโ€ฆ"; -"screen_reset_encryption_password_subtitle" = "Confirm that you want to reset your encryption."; +"screen_reset_encryption_password_subtitle" = "Confirm that you want to reset your identity."; "screen_reset_encryption_password_title" = "Enter your account password to continue"; +"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_room_alias_resolver_resolve_alias_failure" = "Failed to resolve room alias."; "screen_room_attachment_source_camera" = "Camera"; "screen_room_attachment_source_camera_video" = "Record video"; @@ -797,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "Have you saved your recovery key?"; "screen_start_chat_error_starting_chat" = "An error occurred when trying to start a chat"; "screen_view_location_title" = "Location"; -"screen_waitlist_message" = "There's a high demand for %1$@ on %2$@ at the moment. Come back to the app in a few days and try again.\n\nThanks for your patience!"; -"screen_waitlist_title" = "Youโ€™re almost there."; -"screen_waitlist_title_success" = "You're in."; "screen_welcome_bullet_1" = "Calls, polls, search and more will be added later this year."; "screen_welcome_bullet_2" = "Message history for encrypted rooms isnโ€™t available yet."; "screen_welcome_bullet_3" = "Weโ€™d love to hear from you, let us know what you think via the settings page."; @@ -974,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "Sign out"; "screen_signout_confirmation_dialog_title" = "Sign out"; "screen_signout_preference_item" = "Sign out"; -"screen_waitlist_message_success" = "Welcome to %1$@!"; diff --git a/ElementX/Resources/Localizations/es.lproj/Localizable.strings b/ElementX/Resources/Localizations/es.lproj/Localizable.strings index 39f05f6749..7a6f58f87c 100644 --- a/ElementX/Resources/Localizations/es.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/es.lproj/Localizable.strings @@ -27,17 +27,20 @@ "action_back" = "Atrรกs"; "action_call" = "Call"; "action_cancel" = "Cancelar"; +"action_cancel_for_now" = "Cancel for now"; "action_choose_photo" = "Elegir foto"; "action_clear" = "Borrar"; "action_close" = "Cerrar"; "action_complete_verification" = "Completar verificaciรณn"; "action_confirm" = "Confirmar"; +"action_confirm_password" = "Confirm password"; "action_continue" = "Continuar"; "action_copy" = "Copiar"; "action_copy_link" = "Copiar enlace"; "action_copy_link_to_message" = "Copiar enlace al mensaje"; "action_create" = "Crear"; "action_create_a_room" = "Crear una sala"; +"action_deactivate" = "Deactivate"; "action_decline" = "Rechazar"; "action_delete_poll" = "Eliminar encuesta"; "action_disable" = "Desactivar"; @@ -70,6 +73,7 @@ "action_ok" = "OK"; "action_open_settings" = "Ajustes"; "action_open_with" = "Abrir con"; +"action_pin" = "Pin"; "action_quick_reply" = "Respuesta rรกpida"; "action_quote" = "Citar"; "action_react" = "Reaccionar"; @@ -80,6 +84,7 @@ "action_report_bug" = "Informar de un error"; "action_report_content" = "Reportar Contenido"; "action_reset" = "Restablecer"; +"action_reset_identity" = "Reset identity"; "action_retry" = "Reintentar"; "action_retry_decryption" = "Reintentar descifrado"; "action_save" = "Guardar"; @@ -99,10 +104,18 @@ "action_take_photo" = "Hacer foto"; "action_tap_for_options" = "Toca para ver opciones"; "action_try_again" = "Intรฉntalo de nuevo"; +"action_unpin" = "Unpin"; +"action_view_in_timeline" = "View in timeline"; "action_view_source" = "Ver Fuente"; "action_yes" = "Sรญ"; "action.load_more" = "Cargar mรกs"; -"action.pin" = "Pin"; +"action_deactivate_account" = "Deactivate account"; +"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" = "Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices."; +"banner.set_up_recovery.title" = "Set up recovery"; "common_about" = "Acerca de"; "common_acceptable_use_policy" = "Polรญtica de uso aceptable"; "common_advanced_settings" = "Ajustes avanzados"; @@ -214,6 +227,7 @@ "common_waiting_for_decryption_key" = "Esperando este mensaje"; "common.do_not_show_this_again" = "Do not show this again"; "common.open_source_licenses" = "Open source licenses"; +"common.pinned" = "Pinned"; "common.send_to" = "Send to"; "common_no_room_name" = "No room name"; "common_poll_end_confirmation" = "ยฟEstรกs seguro de que quieres finalizar esta encuesta?"; @@ -244,6 +258,7 @@ "emoji_picker_category_people" = "Emojis y personas"; "emoji_picker_category_places" = "Viajes y lugares"; "emoji_picker_category_symbols" = "Sรญmbolos"; +"error_account_creation_not_possible" = "Your homeserver needs to be upgraded to support Matrix Authentication Service and account creation."; "error_failed_creating_the_permalink" = "No se pudo crear el enlace permanente"; "error_failed_loading_map" = "%1$@ no pudo cargar el mapa. Por favor vuelve a intentarlo mรกs tarde."; "error_failed_loading_messages" = "Error al cargar mensajes"; @@ -254,6 +269,8 @@ "error_some_messages_have_not_been_sent" = "Algunos mensajes no se han enviado"; "error_unknown" = "Lo siento, se ha producido un error"; "event_shield_reason_authenticity_not_guaranteed" = "The authenticity of this encrypted message can't be guaranteed on this device."; +"event_shield_reason_previously_verified" = "Encrypted by a previously-verified user."; +"event_shield_reason_sent_in_clear" = "Not encrypted."; "event_shield_reason_unknown_device" = "Encrypted by an unknown or deleted device."; "event_shield_reason_unsigned_device" = "Encrypted by a device not verified by its owner."; "event_shield_reason_unverified_identity" = "Encrypted by an unverified user."; @@ -275,11 +292,14 @@ "notification_inline_reply_failed" = "** No se ha podido enviar - por favor, abre la sala"; "notification_invitation_action_reject" = "Rechazar"; "notification_invite_body" = "Te invitรณ a chatear"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "notification_mentioned_you_body" = "Te mencionรณ: %1$@"; "notification_new_messages" = "Mensajes nuevos"; "notification_reaction_body" = "Reaccionรณ con %1$@"; "notification_room_invite_body" = "Te invitรณ a unirte a la sala"; +"notification_room_invite_body_with_sender" = "%1$@ invited you to join the room"; "notification_sender_me" = "Yo"; +"notification_sender_mention_reply" = "%1$@ mentioned or replied"; "notification_test_push_notification_content" = "ยกEstรกs viendo la notificaciรณn! ยกHaz clic en mรญ!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -312,10 +332,27 @@ "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_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_pinned_timeline_screen_title_empty" = "Pinned messages"; +"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" = "Notificar a toda la sala"; -"screen.room.pinned_banner_indicator" = "%1$@ of %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ Pinned messages"; -"screen.room.pinned_banner_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_details_pinned_events_row_title" = "Pinned messages"; +"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_account_provider_change" = "Cambiar el proveedor de la cuenta"; "screen_account_provider_form_hint" = "Direcciรณn del servidor principal"; "screen_account_provider_form_notice" = "Introduzca un tรฉrmino de bรบsqueda o una direcciรณn de dominio."; @@ -398,6 +435,7 @@ "screen_chat_backup_recovery_action_confirm_description" = "La copia de seguridad de tus chats no estรก sincronizada ahora mismo."; "screen_chat_backup_recovery_action_setup" = "Configurar la clave de recuperaciรณn"; "screen_chat_backup_recovery_action_setup_description" = "Accede a tus mensajes cifrados si pierdes todos tus dispositivos o cierras sesiรณn de %1$@ en cualquier lugar."; +"screen_create_account_title" = "Create account"; "screen_create_new_recovery_key_list_item_1" = "Open %1$@ in a desktop device"; "screen_create_new_recovery_key_list_item_2" = "Sign into your account again"; "screen_create_new_recovery_key_list_item_3" = "When asked to verify your device, select %1$@"; @@ -421,6 +459,17 @@ "screen_create_room_public_option_description" = "Los mensajes no estรกn cifrados y cualquiera puede leerlos. Puedes activar la encriptaciรณn mรกs adelante."; "screen_create_room_public_option_title" = "Sala pรบblica (cualquiera)"; "screen_create_room_topic_label" = "Tema (opcional)"; +"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_edit_poll_delete_confirmation" = "ยฟSeguro que quieres eliminar esta encuesta?"; "screen_edit_profile_display_name" = "Nombre pรบblico"; "screen_edit_profile_display_name_placeholder" = "Tu nombre visible"; @@ -428,12 +477,20 @@ "screen_edit_profile_error_title" = "No se puede actualizar el perfil"; "screen_edit_profile_title" = "Editar perfil"; "screen_edit_profile_updating_details" = "Actualizando perfil..."; +"screen_encryption_reset_action_continue_reset" = "Continue reset"; +"screen_encryption_reset_bullet_1" = "Your account details, contacts, preferences, and chat list will be kept"; +"screen_encryption_reset_bullet_2" = "You will lose your existing message history"; +"screen_encryption_reset_bullet_3" = "You will need to verify all your existing devices and contacts again"; +"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_identity_confirmation_create_new_recovery_key" = "Create a new recovery key"; "screen_identity_confirmation_subtitle" = "Verifica este dispositivo para configurar la mensajerรญa segura."; "screen_identity_confirmation_title" = "Confirma que eres tรบ"; +"screen_identity_confirmation_use_another_device" = "Usar otro dispositivo"; +"screen_identity_confirmation_use_recovery_key" = "Use recovery key"; "screen_identity_confirmed_subtitle" = "Ahora puedes leer o enviar mensajes de forma segura y cualquier persona con la que chatees tambiรฉn puede confiar en este dispositivo."; "screen_identity_confirmed_title" = "Dispositivo verificado"; -"screen_identity_use_another_device" = "Use another device"; "screen_identity_waiting_on_other_device" = "Waiting on other deviceโ€ฆ"; "screen_invites_decline_chat_message" = "ยฟEstรกs seguro de que quieres rechazar la invitaciรณn a unirte a %1$@?"; "screen_invites_decline_chat_title" = "Rechazar la invitaciรณn"; @@ -556,7 +613,6 @@ "screen_recovery_key_confirm_error_content" = "Por favor, intรฉntalo de nuevo para confirmar el acceso a tu copia de seguridad del chat."; "screen_recovery_key_confirm_error_title" = "Clave de recuperaciรณn incorrecta"; "screen_recovery_key_confirm_key_description" = "Introduce el cรณdigo de 48 caracteres."; -"screen_recovery_key_confirm_key_label" = "Recovery key or passcode"; "screen_recovery_key_confirm_key_placeholder" = "Ingresar..."; "screen_recovery_key_confirm_lost_recovery_key" = "Lost your recovery key?"; "screen_recovery_key_confirm_success" = "Clave de recuperaciรณn confirmada"; @@ -577,6 +633,14 @@ "screen_report_content_block_user_hint" = "Marque si quieres ocultar todos los mensajes actuales y futuros de este usuario"; "screen_report_content_explanation" = "Este mensaje se notificarรก al administrador de su homeserver. No podrรกn leer ningรบn mensaje cifrado."; "screen_report_content_hint" = "Motivo para denunciar este contenido"; +"screen_reset_encryption_confirmation_alert_action" = "Yes, reset now"; +"screen_reset_encryption_confirmation_alert_subtitle" = "This process is irreversible."; +"screen_reset_encryption_confirmation_alert_title" = "Are you sure you want to reset your identity?"; +"screen_reset_encryption_password_placeholder" = "Enterโ€ฆ"; +"screen_reset_encryption_password_subtitle" = "Confirm that you want to reset your identity."; +"screen_reset_encryption_password_title" = "Enter your account password to continue"; +"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_room_alias_resolver_resolve_alias_failure" = "Failed to resolve room alias."; "screen_room_attachment_source_camera" = "Cรกmara"; "screen_room_attachment_source_camera_video" = "Grabar video"; @@ -775,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "ยฟHas guardado tu clave de recuperaciรณn?"; "screen_start_chat_error_starting_chat" = "Se ha producido un error al intentar iniciar un chat"; "screen_view_location_title" = "Ubicaciรณn"; -"screen_waitlist_message" = "Hay una gran demanda para %1$@ en %2$@ en este momento. Vuelve a la aplicaciรณn en unos dรญas e intรฉntalo de nuevo.\n\nยกGracias por tu paciencia!"; -"screen_waitlist_title" = "Ya casi has terminado."; -"screen_waitlist_title_success" = "Estรกs dentro."; "screen_welcome_bullet_1" = "Las llamadas, las encuestas, la bรบsqueda y mรกs se agregarรกn mรกs adelante este aรฑo."; "screen_welcome_bullet_2" = "El historial de mensajes de las salas cifradas aรบn no estรก disponible."; "screen_welcome_bullet_3" = "Nos encantarรญa saber de ti, haznos saber lo que piensas a travรฉs de la pรกgina de configuraciรณn."; @@ -834,6 +895,12 @@ "state_event_room_name_removed_by_you" = "Eliminaste el nombre de la sala"; "state_event_room_none" = "%1$@ no hizo cambios"; "state_event_room_none_by_you" = "No has hecho ningรบn cambio"; +"state_event_room_pinned_events_changed" = "%1$@ changed the pinned messages"; +"state_event_room_pinned_events_changed_by_you" = "You changed the pinned messages"; +"state_event_room_pinned_events_pinned" = "%1$@ pinned a message"; +"state_event_room_pinned_events_pinned_by_you" = "You pinned a message"; +"state_event_room_pinned_events_unpinned" = "%1$@ unpinned a message"; +"state_event_room_pinned_events_unpinned_by_you" = "You unpinned a message"; "state_event_room_reject" = "%1$@ rechazรณ la invitaciรณn"; "state_event_room_reject_by_you" = "Rechazaste la invitaciรณn"; "state_event_room_remove" = "%1$@ echรณ a %2$@"; @@ -921,6 +988,7 @@ "screen_dm_details_unblock_user" = "Desbloquear usuario"; "screen_edit_poll_delete_confirmation_title" = "Eliminar encuesta"; "screen_edit_poll_title" = "Editar encuesta"; +"screen_identity_use_another_device" = "Usar otro dispositivo"; "screen_login_subtitle" = "Matrix es una red abierta para una comunicaciรณn segura y descentralizada."; "screen_qr_code_login_invalid_scan_state_retry_button" = "Intรฉntalo de nuevo"; "screen_report_content_block_user" = "Bloquear usuario"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "Cerrar sesiรณn"; "screen_signout_confirmation_dialog_title" = "Cerrar sesiรณn"; "screen_signout_preference_item" = "Cerrar sesiรณn"; -"screen_waitlist_message_success" = "ยกBienvenido a %1$@!"; diff --git a/ElementX/Resources/Localizations/es.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/es.lproj/Localizable.stringsdict index 70d8bd3955..738d81de9b 100644 --- a/ElementX/Resources/Localizations/es.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/es.lproj/Localizable.stringsdict @@ -194,6 +194,22 @@ PIN incorrecto. Tienes %1$d oportunidades mรกs + 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 diff --git a/ElementX/Resources/Localizations/et.lproj/Localizable.strings b/ElementX/Resources/Localizations/et.lproj/Localizable.strings index ff2b75cc8b..fdc0703ecb 100644 --- a/ElementX/Resources/Localizations/et.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/et.lproj/Localizable.strings @@ -25,19 +25,22 @@ "action_accept" = "Nรตustu"; "action_add_to_timeline" = "Lisa ajajoonele"; "action_back" = "Tagasi"; -"action_call" = "Helista kasutajale"; +"action_call" = "Helista"; "action_cancel" = "Loobu"; +"action_cancel_for_now" = "Hetkel jรคta tegemata"; "action_choose_photo" = "Vali foto"; "action_clear" = "Selge"; "action_close" = "Sulge"; "action_complete_verification" = "Tee verifitseerimine lรตpuni"; "action_confirm" = "Kinnita"; +"action_confirm_password" = "Korda salasรตna"; "action_continue" = "Jรคtka"; "action_copy" = "Kopeeri"; "action_copy_link" = "Kopeeri link"; "action_copy_link_to_message" = "Kopeeri sรตnumi link"; "action_create" = "Loo"; "action_create_a_room" = "Loo jututuba"; +"action_deactivate" = "Deactivate"; "action_decline" = "Keeldu"; "action_delete_poll" = "Kustuta kรผsitlus"; "action_disable" = "Lรผlita vรคlja"; @@ -63,13 +66,14 @@ "action_leave_room" = "Lahku jututoast"; "action_manage_account" = "Halda kasutajakontot"; "action_manage_devices" = "Halda seadmeid"; -"action_message" = "Saada sรตnum kasutajale"; +"action_message" = "Saada sรตnum"; "action_next" = "Edasi"; "action_no" = "Ei"; "action_not_now" = "Mitte praegu"; "action_ok" = "OK"; "action_open_settings" = "Seadistused"; "action_open_with" = "Ava rakendusega"; +"action_pin" = "Tรตsta esile"; "action_quick_reply" = "Kiirvastus"; "action_quote" = "Tsiteeri"; "action_react" = "Reageeri"; @@ -80,6 +84,7 @@ "action_report_bug" = "Teata veast"; "action_report_content" = "Teata sisust haldurile"; "action_reset" = "Lรคhtesta"; +"action_reset_identity" = "Lรคhtesta oma identiteet"; "action_retry" = "Proovi uuesti"; "action_retry_decryption" = "Proovi dekrรผptimist uuesti"; "action_save" = "Salvesta"; @@ -99,10 +104,18 @@ "action_take_photo" = "Tee pilt"; "action_tap_for_options" = "Valikuteks klรตpsa"; "action_try_again" = "Proovi uuesti"; +"action_unpin" = "Eemalda esiletรตstmine"; +"action_view_in_timeline" = "Vaata ajajoonel"; "action_view_source" = "Vaata lรคhtekoodi"; "action_yes" = "Jah"; "action.load_more" = "Nรคita veel"; -"action.pin" = "Kinnita"; +"action_deactivate_account" = "Eemalda konto kasutusest"; +"banner_migrate_to_native_sliding_sync_action" = "Logi vรคlja ja uuenda"; +"banner_migrate_to_native_sliding_sync_description" = "Sinu koduserver toetab uut ja kiiremat protokolli. Uuendamiseks logi korraks rakendusest vรคlja ja siis tagasi. Mingil hetkel tulevikus vana protokoll eemaldatakse kasutusest ja tehes uuenduse nรผรผd vรคldid hilisemat sundkorras uuendust."; +"banner_migrate_to_native_sliding_sync_force_logout_title" = "Sinu koduserver enam ei toeta vana protokolli. Jรคtkamaks rakenduse kasutamist palun logi vรคlja ning seejรคrel tagasi."; +"banner_migrate_to_native_sliding_sync_title" = "Saadaval on uuendus"; +"banner.set_up_recovery.content" = "Loo uus taastevรตti, mida saad kasutada oma krรผptitud sรตnumite ajaloo taastamisel olukorras, kus kaotad ligipรครคsu oma seadmetele."; +"banner.set_up_recovery.title" = "Seadista taastamine"; "common_about" = "Rakenduse teave"; "common_acceptable_use_policy" = "Vastuvรตetava kasutamise pรตhimรตtted"; "common_advanced_settings" = "Tรคiendavad seadistused"; @@ -147,7 +160,7 @@ "common_message_layout" = "Sรตnumi paigutus"; "common_message_removed" = "Sรตnum on eemaldatud"; "common_modern" = "Kaasaegne"; -"common_mute" = "Summutamine"; +"common_mute" = "Summutatud"; "common_no_results" = "Otsingul pole tulemusi"; "common_offline" = "Vรตrgust vรคljas"; "common_optic_id_ios" = "Optic ID"; @@ -178,7 +191,7 @@ "common_search_for_someone" = "Otsi kedagi"; "common_search_results" = "Otsingutulemused"; "common_security" = "Turvalisus"; -"common_seen_by" = "Seda nรคgi"; +"common_seen_by" = "Seda nรคgi(d)"; "common_sending" = "Saadame..."; "common_sending_failed" = "Saatmine ei รตnnestunud"; "common_sent" = "Saadetud"; @@ -214,6 +227,7 @@ "common_waiting_for_decryption_key" = "Ootame selle sรตnumi dekrรผptimisvรตtit"; "common.do_not_show_this_again" = "ร„ra enam nรคita seda uuesti"; "common.open_source_licenses" = "Avatud lรคhtekoodiga litsentsid"; +"common.pinned" = "Esiletรตstetud"; "common.send_to" = "Saada kasutajale"; "common_no_room_name" = "Jututoal puudub nimi"; "common_poll_end_confirmation" = "Kas oled kindel, et soovid selle kรผsitluse lรตpetada?"; @@ -223,7 +237,7 @@ "common_verify_device" = "Verifitseeri seade"; "confirm_recovery_key_banner_message" = "Sinu vestluste varukoopia pole hetkel sรผnkroonis. Sรคilitamaks ligipรครคsu vestluse varukoopiale palun sisesta oma taastevรตti."; "confirm_recovery_key_banner_title" = "Sisesta oma taastevรตti"; -"crash_detection_dialog_content" = "%1$@ jooksis kokku viimatu kui seda kasutasid. Kas tahaksid selle kohta meile aruande saata?"; +"crash_detection_dialog_content" = "%1$@ jooksis kokku viimati, kui seda kasutasid. Kas tahaksid selle kohta meile veateate saata?"; "dialog_permission_camera" = "Selleks, et rakendus saaks kaamerat kasutada, palun luba see sรผsteemi seadistuses."; "dialog_permission_generic" = "Palun luba sรผsteemi seadistustest vajalikud รตigused."; "dialog_permission_location_description_ios" = "Luba รตigused Seadistused -> Asukoht valikust."; @@ -244,6 +258,7 @@ "emoji_picker_category_people" = "Emotikonid ja inimesed"; "emoji_picker_category_places" = "Reisimine ja kohad"; "emoji_picker_category_symbols" = "Sรผmbolid"; +"error_account_creation_not_possible" = "Selleks et koos kasutajakonto loomisega toimiks Matrix Authentication Service'i tugi, vajab sinu koduserver uuendamist."; "error_failed_creating_the_permalink" = "Pรผsilingi loomine ei รตnnestumud"; "error_failed_loading_map" = "%1$@ kaardi laadimine ei รตnnestunud. Palun proovi hiljem uuesti."; "error_failed_loading_messages" = "Sรตnumite laadimine ei รตnnestunud"; @@ -254,11 +269,13 @@ "error_some_messages_have_not_been_sent" = "Mรตned sรตnumid on saatmata"; "error_unknown" = "Vabandust, ilmnes viga"; "event_shield_reason_authenticity_not_guaranteed" = "Selle krรผptitud sรตnumi tรตepรคrasus pole selles seadmes tagatud."; +"event_shield_reason_previously_verified" = "Krรผptitud varem verifitseeritud kasutaja poolt"; +"event_shield_reason_sent_in_clear" = "Pole krรผptitud."; "event_shield_reason_unknown_device" = "Krรผptitud tundmatu vรตi kustutatud seadme poolt."; "event_shield_reason_unsigned_device" = "Krรผptitud seadme poolt, mida tema omanik pole verifitseerinud."; "event_shield_reason_unverified_identity" = "Krรผptitud verifitseerimata kasutaja poolt."; "full_screen_intent_banner_message" = "Selleks, et sul ainsamgi tรคhtis kรตne ei jรครคks mรคrkamata, siis palun muuda oma nutiseadme seadistusi nii, et lukustusvaates oleksid tรคisekraani mรตรตtu teavitused."; -"full_screen_intent_banner_title" = "Tรคiusta oma telefonikรตnede kogemust"; +"full_screen_intent_banner_title" = "Sinu tรตhusad telefonikรตned"; "invite_friends_rich_title" = "๐Ÿ”๏ธ Liitu minuga rakenduses %1$@"; "invite_friends_text" = "Hei, suhtle minuga %1$@ vรตrgus: %2$@"; "leave_conversation_alert_subtitle" = "Kas sa oled kindel, et soovid sellest vestlusest lahkuda? See vestlus pole avalik ja uuesti liitumiseks vajad kutset."; @@ -275,11 +292,14 @@ "notification_inline_reply_failed" = "** Saatmine ei รตnnestunud - palun ava jututoa tรคisvaade"; "notification_invitation_action_reject" = "Lรผkka tagasi"; "notification_invite_body" = "Kutse osalema vestluses"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "notification_mentioned_you_body" = "Mainis sind: %1$@"; "notification_new_messages" = "Uued sรตnumid"; "notification_reaction_body" = "Reageeris nii: %1$@"; "notification_room_invite_body" = "Saatis sulle kutse jututuppa"; +"notification_room_invite_body_with_sender" = "%1$@ invited you to join the room"; "notification_sender_me" = "Mina"; +"notification_sender_mention_reply" = "%1$@ mainis vรตi vastas"; "notification_test_push_notification_content" = "See ongi teavitus! Klรตpsi mind!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -312,10 +332,27 @@ "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_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_pinned_timeline_screen_title_empty" = "Esiletรตstetud sรตnumid"; +"screen_reset_encryption_password_error" = "Tekkis teadmata viga. Palun kontrolli, kas sinu kasutajakonto salasรตna on รตige ja proovi uuesti."; +"screen_resolve_send_failure_changed_identity_primary_button_title" = "Unusta verifitseerimine ja saada ikkagi"; +"screen_resolve_send_failure_changed_identity_subtitle" = "Sa vรตid jรคtta verifitseerimisvea tรคhelepanuta ja sรตnumi ikkagi saata vรตi katkestad saatmise ja peale kasutaja %1$@ verifitseerimist proovid seda uuesti."; +"screen_resolve_send_failure_changed_identity_title" = "Sinu sรตnum on saatmata, kuna kasutaja %1$@ verifitseeritud identiteet on muutunud."; +"screen_resolve_send_failure_unsigned_device_primary_button_title" = "Saada sรตnum ikkagi"; +"screen_resolve_send_failure_unsigned_device_subtitle" = "%1$@ kasutab รผhte vรตi enamat verifitseerimata seadet. Sa vรตid sรตnumi ikkagi saata vรตi katkestad selle ning ootad kuni %2$@ on kรตik oma seadmed verifitseerinud ning proovid seejรคrel uuesti."; +"screen_resolve_send_failure_unsigned_device_title" = "Sinu sรตnum on saatmata, kuna %1$@ pole verifitseerinud kรตiki oma seadmeid"; +"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.pinned_banner_indicator" = "%1$@ / %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ kinnitatud sรตnumit"; -"screen.room.pinned_banner_view_all_button_title" = "Nรคita 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_details_pinned_events_row_title" = "Esiletรตstetud sรตnumid"; +"screen_timeline_item_menu_send_failure_changed_identity" = "Sรตnum on saatmata, kuna kasutaja %1$@ verifitseeritud identiteet on muutunud."; +"screen_timeline_item_menu_send_failure_unsigned_device" = "Sรตnum on saatmata, kuna %1$@ pole verifitseerinud kรตiki oma seadmeid."; +"screen_timeline_item_menu_send_failure_you_unsigned_device" = "Kuna sa pole รผks vรตi enamgi oma seadet verifitseerinud, siis sinu sรตnum on saatmata."; "screen_account_provider_change" = "Muuda teenusepakkujat"; "screen_account_provider_form_hint" = "Koduserveri aadress"; "screen_account_provider_form_notice" = "Sisesta otsingusรตna vรตi domeeni nimi."; @@ -336,8 +373,8 @@ "screen_analytics_prompt_read_terms" = "Sa vรตid lugeda meie kasutustingimusi %1$@"; "screen_analytics_prompt_read_terms_content_link" = "siin"; "screen_analytics_prompt_settings" = "Selle valiku saad igal ajal vรคlja lรผlitada"; -"screen_analytics_prompt_third_party_sharing" = "Me ei jaga andmeid kolmandate osapooltega"; -"screen_analytics_prompt_title" = "Aita parandada %1$@ rakendust"; +"screen_analytics_prompt_third_party_sharing" = "Me ei jaga sinu andmeid kolmandate osapooltega"; +"screen_analytics_prompt_title" = "Aita parandada rakendust %1$@"; "screen_analytics_settings_share_data" = "Jaga andmeid rakenduse kasutuse kohta"; "screen_app_lock_biometric_authentication" = "biomeetrilist autentimist"; "screen_app_lock_biometric_unlock" = "biomeetrilist lukustuse eemaldamist"; @@ -356,7 +393,7 @@ "screen_app_lock_setup_biometric_unlock_subtitle" = "Sรครคsta aega ja kasuta alati %1$@ rakenduse lukustuse eemaldamiseks"; "screen_app_lock_setup_choose_pin" = "Vali PIN-kood"; "screen_app_lock_setup_confirm_pin" = "Korda PIN-koodi"; -"screen_app_lock_setup_pin_context" = "Lisamaks oma %1$@ vestlustele turvalisust ja privaatsust, lukusta oma nutiseade.\n\nVali midagi, mis hรคsti meelde jรครคb. Kui unustad selle PIN-koodi, siis turvakaalutlustel logitakse sind rakendusest vรคlja."; +"screen_app_lock_setup_pin_context" = "Lisamaks oma %1$@ rakenduse vestlustele turvalisust ja privaatsust, lukusta oma nutiseade.\n\nVali midagi, mis hรคsti meelde jรครคb. Kui unustad selle PIN-koodi, siis turvakaalutlustel logitakse sind rakendusest vรคlja."; "screen_app_lock_setup_pin_forbidden_dialog_content" = "Turvakaalutlustel sa ei saa sellist PIN-koodi kasutada"; "screen_app_lock_setup_pin_forbidden_dialog_title" = "Kasuta mรตnda teist PIN-koodi"; "screen_app_lock_setup_pin_mismatch_dialog_content" = "Palun sisesta sama PIN-kood kaks korda"; @@ -384,7 +421,7 @@ "screen_change_account_provider_title" = "Muuda teenusepakkujat"; "screen_change_server_error_invalid_homeserver" = "Me ei suutnud luuaรผhendust selle koduserveriga. Palun kontrolli, kas koduserveri aadress on รตige. Kui aadress on รตige, siis tรคiendavat teavet oskab sulle anda koduserveri haldaja."; "screen_change_server_error_invalid_well_known" = "Sliding sync reลพiim pole saadaval vea tรตttu well-known failis:\n%1$@"; -"screen_change_server_error_no_sliding_sync_message" = "See koduserver hetkel ei toeta Sliding sync reลพiimi"; +"screen_change_server_error_no_sliding_sync_message" = "See koduserver hetkel ei toeta โ€žSliding syncโ€œ reลพiimi"; "screen_change_server_form_header" = "Koduserveri url"; "screen_change_server_form_notice" = "Sa saad luua รผhendust vaid olemasoleva serveriga, mis toetab Sliding sync reลพiimi. Sinu koduserveri haldur peaks selle seadistama. %1$@"; "screen_change_server_subtitle" = "Mis on sinu koduserveri aadress?"; @@ -398,6 +435,7 @@ "screen_chat_backup_recovery_action_confirm_description" = "Sinu vestluste krรผptograafia varukoopia pole hetkel enam sรผnkroonis."; "screen_chat_backup_recovery_action_setup" = "Seadista krรผptovรตtmete varundus"; "screen_chat_backup_recovery_action_setup_description" = "Sรคilita ligipรครคs oma krรผptitud sรตnumitele ka siis, kui sa kaotad kรตik oma seadmed ja/vรตi logid kรตikjal vรคlja rakendusest %1$@."; +"screen_create_account_title" = "Loo kasutajakonto"; "screen_create_new_recovery_key_list_item_1" = "Ava %1$@ tรถรถlauaga seadmes"; "screen_create_new_recovery_key_list_item_2" = "Logi uuesti sisse oma kasutajakontole"; "screen_create_new_recovery_key_list_item_3" = "Kui sul palutakse seadet verifitseerida, vali %1$@"; @@ -421,6 +459,17 @@ "screen_create_room_public_option_description" = "Sรตnumid pole krรผptitud ja neid saavad kรตik lugeda. Soovi korral saad hiljem krรผptimise sisse lรผlitada."; "screen_create_room_public_option_title" = "Avalik jututuba (avatud kรตigile)"; "screen_create_room_topic_label" = "Teema (kui soovid lisada)"; +"screen_deactivate_account_confirmation_dialog_content" = "Palun kinnita uuesti, et soovid eemaldada oma konto kasutusest"; +"screen_deactivate_account_delete_all_messages" = "Kustuta kรตik minu sรตnumid"; +"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" = "Eemalda konto kasutusest"; "screen_edit_poll_delete_confirmation" = "Kas sa oled kindel, et soovid selle kรผsitluse kustutada?"; "screen_edit_profile_display_name" = "Kuvatav nimi"; "screen_edit_profile_display_name_placeholder" = "Sinu kuvatav nimi"; @@ -428,12 +477,20 @@ "screen_edit_profile_error_title" = "Profiili uuendamine ei รตnnestunud"; "screen_edit_profile_title" = "Muuda profiili"; "screen_edit_profile_updating_details" = "Profiil on muutmisel..."; +"screen_encryption_reset_action_continue_reset" = "Jรคtka lรคhtestamisega"; +"screen_encryption_reset_bullet_1" = "Sinu kasutajakonto andmed, kontaktid, eelistused ja vestluste loend sรคiluvad"; +"screen_encryption_reset_bullet_2" = "Sa kaotad seniste sรตnumite ajaloo"; +"screen_encryption_reset_bullet_3" = "Sa pead kรตik oma olemasolevad seadmed ja kontaktid uuesti verifitseerima"; +"screen_encryption_reset_footer" = "Lรคhtesta oma identiteet vaid siis, kui sul pole ligipรครคsu mitte รผhelegi oma seadmele ja sa oled kaotanud oma taastevรตtme."; +"screen_encryption_reset_title" = "Kui sa รผhtegi muud vรตimalust ei leia, siis lรคhtesta oma identiteet."; +"screen_identity_confirmation_cannot_confirm" = "Kas kinnitamine pole vรตimalik?"; "screen_identity_confirmation_create_new_recovery_key" = "Loo uus taastevรตti"; "screen_identity_confirmation_subtitle" = "Krรผptitud sรตnumivahetuse tagamiseks verifitseeri see seade."; "screen_identity_confirmation_title" = "Kinnita, et see oled sina"; +"screen_identity_confirmation_use_another_device" = "Kasuta teist seadet"; +"screen_identity_confirmation_use_recovery_key" = "Kasuta taastevรตtit"; "screen_identity_confirmed_subtitle" = "Nรผรผd saad saata vรตi lugeda sรตnumeid turvaliselt ning kรตik sinu vestluspartnerid vรตivad usaldada seda seadet."; "screen_identity_confirmed_title" = "Seade on verifitseeritud"; -"screen_identity_use_another_device" = "Kasuta mรตnda muud seadet"; "screen_identity_waiting_on_other_device" = "Ootame teise seadme jรคrgiโ€ฆ"; "screen_invites_decline_chat_message" = "Kas sa oled kindel, et soovid keelduda liitumiskutsest: %1$@?"; "screen_invites_decline_chat_title" = "Lรผkka kutse tagasi"; @@ -520,7 +577,7 @@ "screen_qr_code_login_device_not_signed_in_scan_state_subtitle" = "Teine seade pole sisselogitud"; "screen_qr_code_login_error_cancelled_subtitle" = "Sisselogimine katkestati teises seadmes."; "screen_qr_code_login_error_cancelled_title" = "Sisselogimispรคring on tรผhistatud"; -"screen_qr_code_login_error_declined_subtitle" = "Sisselogimisest on teise seadmes keeldutud."; +"screen_qr_code_login_error_declined_subtitle" = "Sisselogimisest on teises seadmes keeldutud."; "screen_qr_code_login_error_declined_title" = "Sisselogimisest on keeldutud"; "screen_qr_code_login_error_expired_subtitle" = "Sisselogimine aegus. Palun proovi uuesti."; "screen_qr_code_login_error_expired_title" = "Sisselogimine jรคi etteantud aja jooksul tegemata"; @@ -556,7 +613,6 @@ "screen_recovery_key_confirm_error_content" = "Kinnitamaks ligipรครคsu sinu vestluse varukoopiale, palun proovi uuesti"; "screen_recovery_key_confirm_error_title" = "Vigane taastevรตti"; "screen_recovery_key_confirm_key_description" = "Kui sul on turvavรตti vรตi turvafraas, siis need toimivad ka."; -"screen_recovery_key_confirm_key_label" = "Taastevรตti vรตi turvafraas"; "screen_recovery_key_confirm_key_placeholder" = "Sisesta..."; "screen_recovery_key_confirm_lost_recovery_key" = "Kas sa oled taastevรตtme kaotanud?"; "screen_recovery_key_confirm_success" = "Taastevรตti on kinnitatud"; @@ -577,6 +633,14 @@ "screen_report_content_block_user_hint" = "Vali see eelistus, kui sa soovid peita selle kasutaja kรตik senised ja tulevased sรตnumid"; "screen_report_content_explanation" = "Teade selle sรตnumi kohta edastatakse sinu koduserveri haldajale. Haldajal ei ole vรตimalik lugeda krรผptitud sรตnumite sisu."; "screen_report_content_hint" = "Sellest sisust teatamise pรตhjus"; +"screen_reset_encryption_confirmation_alert_action" = "Jah, lรคhtesta nรผรผd"; +"screen_reset_encryption_confirmation_alert_subtitle" = "See tegevus on tagasipรถรถrdumatu."; +"screen_reset_encryption_confirmation_alert_title" = "Kas sa oled kindel, et soovid oma andmete krรผptimist lรคhtestada?"; +"screen_reset_encryption_password_placeholder" = "Sisesta..."; +"screen_reset_encryption_password_subtitle" = "Palun kinnita, et soovid oma andmete krรผptimist lรคhtestada."; +"screen_reset_encryption_password_title" = "Jรคtkamaks sisesta oma kasutajakonto salasรตna"; +"screen_reset_identity_confirmation_subtitle" = "Oma vรตrguidentiteedi lรคhtestamiseks suuname sind %1$@ kasutajakonto halduse lehele. Hiljem suunatakse sind tagasi sama rakenduse juurde."; +"screen_reset_identity_confirmation_title" = "Sa ei saa seda kinnitada? Ava oma kasutajakonto haldus ja lรคhtesta oma vรตrguidentiteet."; "screen_room_alias_resolver_resolve_alias_failure" = "Jututoa aliasele vastava aadressi tuvastamine ei รตnnestunud."; "screen_room_attachment_source_camera" = "Kaamera"; "screen_room_attachment_source_camera_video" = "Salvesta video"; @@ -729,7 +793,7 @@ "screen_server_confirmation_change_server" = "Muuda teenusepakujat"; "screen_server_confirmation_message_login_element_dot_io" = "Privaatne server Elemendi tรถรถtajate jaoks."; "screen_server_confirmation_message_login_matrix_dot_org" = "Matrix on avatud vรตrk turvalise ja hajutatud suhtluse jaoks."; -"screen_server_confirmation_message_register" = "See on koht, kus sinu vestlused elavad โ€“ just nagu kasutaksid oma e-kirjade sรคilitamiseks e-postitenuse pakkujat."; +"screen_server_confirmation_message_register" = "See on koht, kus sinu vestlused elavad โ€“ just nagu kasutaksid oma e-kirjade sรคilitamiseks e-postiteenuse pakkujat."; "screen_server_confirmation_title_login" = "Sa oled sisselogimas koduserverisse %1$@"; "screen_server_confirmation_title_register" = "Sa oled loomas kasutajakontot koduserveris %1$@"; "screen_session_verification_cancelled_subtitle" = "Olukord pole pรคris รตige. Pรคring kas aegus vรตi teine osapool keeldus pรคringule vastamast."; @@ -741,7 +805,7 @@ "screen_session_verification_enter_recovery_key" = "Sisesta taastevรตti"; "screen_session_verification_open_existing_session_subtitle" = "Saamaks ligipรครคsu krรผptitud sรตnumite ajaloole tรตesta et tegemist on sinuga."; "screen_session_verification_open_existing_session_title" = "Ava olemasolev sessioon"; -"screen_session_verification_positive_button_canceled" = "Proovi uuesti verifitseerimist"; +"screen_session_verification_positive_button_canceled" = "Proovi verifitseerimist uuesti"; "screen_session_verification_positive_button_initial" = "Ma olen valmis alustama"; "screen_session_verification_positive_button_verifying_ongoing" = "Ootame kinnitust sobivusele"; "screen_session_verification_ready_subtitle" = "Vรตrdle unikaalset emojide kombinatsiooni"; @@ -775,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "Kas sa oled oma taastevรตtme salvestanud?"; "screen_start_chat_error_starting_chat" = "Vestluse alustamisel tekkis viga"; "screen_view_location_title" = "Asukoht"; -"screen_waitlist_message" = "%1$@ kasutamiseks %2$@ koduserveris on hetkel palju huvilisi. Proovi seda samast rakendusest mรตne pรคeva pรคrast.\n\nTรคname kannatlikkuse eest!"; -"screen_waitlist_title" = "Peaaegu olemas."; -"screen_waitlist_title_success" = "Oled nรผรผd jututoas."; "screen_welcome_bullet_1" = "Kรตned, kรผsitlused, otsing ja palju muud lisanduvad hiljem selle aasta jooksul."; "screen_welcome_bullet_2" = "Krรผptitud jututubade sรตnumite ajalugu pole veel saadaval."; "screen_welcome_bullet_3" = "Me soovime teada mida sa arvad. Seadistuste lehel olevast valikust vรตid saata meile oma kommentaare."; @@ -834,6 +895,12 @@ "state_event_room_name_removed_by_you" = "Sina eemaldasid jututoa nime"; "state_event_room_none" = "%1$@ ei teinud รผhtegi muudatust"; "state_event_room_none_by_you" = "Sina ei teinud รผhtegi muudatust"; +"state_event_room_pinned_events_changed" = "%1$@ muutis esiletรตstetud sรตnumeid"; +"state_event_room_pinned_events_changed_by_you" = "Sina muutsid esiletรตstetud sรตnumeid"; +"state_event_room_pinned_events_pinned" = "%1$@ tรตstis sรตnumi esile"; +"state_event_room_pinned_events_pinned_by_you" = "Sina tรตstsid sรตnumi esile"; +"state_event_room_pinned_events_unpinned" = "%1$@ eemaldas esiletรตstetud sรตnumi"; +"state_event_room_pinned_events_unpinned_by_you" = "Sina eemaldasid esiletรตstetud sรตnumi"; "state_event_room_reject" = "%1$@ lรผkkas kutse tagasi"; "state_event_room_reject_by_you" = "Sina lรผkkasid kutse tagasi"; "state_event_room_remove" = "%1$@ eemaldas jututoast kasutaja %2$@"; @@ -901,15 +968,15 @@ "notification_room_action_mark_as_read" = "Mรคrgi loetuks"; "notification_room_action_quick_reply" = "Kiirvastus"; "screen_room_mentions_at_room_title" = "Kรตik"; -"screen_account_provider_signin_subtitle" = "See on koht, kus sinu vestlused elavad โ€“ just nagu kasutaksid oma e-kirjade sรคilitamiseks e-postitenuse pakkujat."; -"screen_account_provider_signup_subtitle" = "See on koht, kus sinu vestlused elavad โ€“ just nagu kasutaksid oma e-kirjade sรคilitamiseks e-postitenuse pakkujat."; +"screen_account_provider_signin_subtitle" = "See on koht, kus sinu vestlused elavad โ€“ just nagu kasutaksid oma e-kirjade sรคilitamiseks e-postiteenuse pakkujat."; +"screen_account_provider_signup_subtitle" = "See on koht, kus sinu vestlused elavad โ€“ just nagu kasutaksid oma e-kirjade sรคilitamiseks e-postiteenuse pakkujat."; "screen_analytics_settings_help_us_improve" = "Vรตimalike rakenduse vigade leidmiseks palun jaga anonรผรผmset kasutusteavet."; "screen_analytics_settings_read_terms" = "Sa vรตid lugeda meie kasutustingimusi %1$@"; "screen_analytics_settings_read_terms_content_link" = "siin"; "screen_blocked_users_unblock_alert_action" = "Eemalda blokeering"; "screen_blocked_users_unblock_alert_description" = "Nรผรผd nรคed sa jรคlle kรตiki tema sรตnumeid"; "screen_blocked_users_unblock_alert_title" = "Eemalda kasutajalt blokeering"; -"screen_bug_report_rash_logs_alert_title" = "%1$@ jooksis kokku viimatu kui seda kasutasid. Kas tahaksid selle kohta meile aruande saata?"; +"screen_bug_report_rash_logs_alert_title" = "%1$@ jooksis kokku viimati, kui seda kasutasid. Kas tahaksid selle kohta meile veateate saata?"; "screen_create_room_add_people_title" = "Kutsu osalejaid"; "screen_create_room_room_name_label" = "Jututoa nimi"; "screen_create_room_title" = "Loo jututuba"; @@ -921,6 +988,7 @@ "screen_dm_details_unblock_user" = "Eemalda kasutajalt blokeering"; "screen_edit_poll_delete_confirmation_title" = "Kustuta kรผsitlus"; "screen_edit_poll_title" = "Muuda kรผsitlust"; +"screen_identity_use_another_device" = "Kasuta teist seadet"; "screen_login_subtitle" = "Matrix on avatud vรตrk turvalise ja hajutatud suhtluse jaoks."; "screen_qr_code_login_invalid_scan_state_retry_button" = "Proovi uuesti"; "screen_report_content_block_user" = "Blokeeri kasutaja"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "Logi vรคlja"; "screen_signout_confirmation_dialog_title" = "Logi vรคlja"; "screen_signout_preference_item" = "Logi vรคlja"; -"screen_waitlist_message_success" = "Tere tulemast rakendusse %1$@!"; diff --git a/ElementX/Resources/Localizations/et.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/et.lproj/Localizable.stringsdict index 30c31921e4..b25b512850 100644 --- a/ElementX/Resources/Localizations/et.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/et.lproj/Localizable.stringsdict @@ -194,6 +194,22 @@ Vale PIN-kood. Saad proovida veel %1$d korda + screen_pinned_timeline_screen_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d esiletรตstetud sรตnum + other + %1$d esiletรตstetud sรตnumit + + screen_room_member_list_header_title NSStringLocalizedFormatKey @@ -237,9 +253,9 @@ NSStringFormatValueTypeKey d one - %1$@, %2$@ ja veel %3$d huviline + %1$@, %2$@ ja veel %3$d osaleja other - %1$@, %2$@ ja veel %3$d huvilist + %1$@, %2$@ ja veel %3$d osalejat screen_room_typing_many_members_second_component_ios diff --git a/ElementX/Resources/Localizations/fr.lproj/Localizable.strings b/ElementX/Resources/Localizations/fr.lproj/Localizable.strings index cbc0d2aff7..ae8d717f79 100644 --- a/ElementX/Resources/Localizations/fr.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/fr.lproj/Localizable.strings @@ -27,17 +27,20 @@ "action_back" = "Retour"; "action_call" = "Appel"; "action_cancel" = "Annuler"; +"action_cancel_for_now" = "Annuler pour lโ€™instant"; "action_choose_photo" = "Choisir une photo"; "action_clear" = "Effacer"; "action_close" = "Fermer"; "action_complete_verification" = "Terminer la vรฉrification"; "action_confirm" = "Confirmer"; +"action_confirm_password" = "Confirm password"; "action_continue" = "Continuer"; "action_copy" = "Copier"; "action_copy_link" = "Copier le lien"; "action_copy_link_to_message" = "Copier le lien vers le message"; "action_create" = "Crรฉer"; "action_create_a_room" = "Crรฉer un salon"; +"action_deactivate" = "Deactivate"; "action_decline" = "Refuser"; "action_delete_poll" = "Supprimer le sondage"; "action_disable" = "Dรฉsactiver"; @@ -70,6 +73,7 @@ "action_ok" = "OK"; "action_open_settings" = "Ouvrir les paramรจtres"; "action_open_with" = "Ouvrir avec"; +"action_pin" = "ร‰pingler"; "action_quick_reply" = "Rรฉponse rapide"; "action_quote" = "Citer"; "action_react" = "Rรฉagissez"; @@ -80,6 +84,7 @@ "action_report_bug" = "Signaler un problรจme"; "action_report_content" = "Signaler le contenu"; "action_reset" = "Rรฉinitialiser"; +"action_reset_identity" = "Reset identity"; "action_retry" = "Rรฉessayer"; "action_retry_decryption" = "Rรฉessayer le dรฉchiffrement"; "action_save" = "Enregistrer"; @@ -99,10 +104,18 @@ "action_take_photo" = "Prendre une photo"; "action_tap_for_options" = "Appuyez pour afficher les options"; "action_try_again" = "Essayer ร  nouveau"; +"action_unpin" = "Dรฉsรฉpingler"; +"action_view_in_timeline" = "Voir dans la discussion"; "action_view_source" = "Afficher la source"; "action_yes" = "Oui"; "action.load_more" = "Voir plus"; -"action.pin" = "Pin"; +"action_deactivate_account" = "Deactivate account"; +"banner_migrate_to_native_sliding_sync_action" = "Dรฉconnecter et mettre ร  niveau"; +"banner_migrate_to_native_sliding_sync_description" = "Votre serveur prend dรฉsormais en charge un nouveau protocole plus rapide. Dรฉconnectez-vous, puis reconnectez-vous pour effectuer la mise ร  niveau dรจs maintenant. En le faisant tout de suite, vous รฉviterez une dรฉconnexion forcรฉe lorsque l'ancien protocole sera supprimรฉ."; +"banner_migrate_to_native_sliding_sync_force_logout_title" = "Votre serveur dโ€™accueil ne prend plus en charge l'ancien protocole. Veuillez vous dรฉconnecter puis vous reconnecter pour continuer ร  utiliser l'application."; +"banner_migrate_to_native_sliding_sync_title" = "Mise ร  niveau disponible"; +"banner.set_up_recovery.content" = "Gรฉnรฉrez une nouvelle clรฉ de rรฉcupรฉration qui peut รชtre utilisรฉe pour restaurer l'historique de vos messages chiffrรฉs au cas oรน vous perdriez l'accรจs ร  vos appareils."; +"banner.set_up_recovery.title" = "Configurer la rรฉcupรฉration"; "common_about" = "ร€ propos"; "common_acceptable_use_policy" = "Politique dโ€™utilisation acceptable"; "common_advanced_settings" = "Paramรจtres avancรฉs"; @@ -213,7 +226,8 @@ "common_waiting" = "En attente..."; "common_waiting_for_decryption_key" = "En attente de la clรฉ de dรฉchiffrement"; "common.do_not_show_this_again" = "Ne plus afficher"; -"common.open_source_licenses" = "Open source licenses"; +"common.open_source_licenses" = "Licences open source"; +"common.pinned" = "ร‰pinglรฉ"; "common.send_to" = "Envoyer vers"; "common_no_room_name" = "Salon sans nom"; "common_poll_end_confirmation" = "รŠtes-vous sรปr de vouloir mettre fin ร  ce sondageย ?"; @@ -244,6 +258,7 @@ "emoji_picker_category_people" = "ร‰moticรดnes et personnes"; "emoji_picker_category_places" = "Voyages & lieux"; "emoji_picker_category_symbols" = "Symboles"; +"error_account_creation_not_possible" = "Votre serveur dโ€™accueil doit รชtre mis ร  jour pour prendre en charge le protocole MAS (Matrix Authentication Service) et la crรฉation de compte."; "error_failed_creating_the_permalink" = "ร‰chec de la crรฉation du permalien"; "error_failed_loading_map" = "%1$@ nโ€™a pas pu charger la carte. Veuillez rรฉessayer ultรฉrieurement."; "error_failed_loading_messages" = "ร‰chec du chargement des messages"; @@ -253,10 +268,12 @@ "error_no_compatible_app_found" = "Aucune application compatible nโ€™a รฉtรฉ trouvรฉe pour gรฉrer cette action."; "error_some_messages_have_not_been_sent" = "Certains messages nโ€™ont pas รฉtรฉ envoyรฉs"; "error_unknown" = "Dรฉsolรฉ, une erreur sโ€™est produite"; -"event_shield_reason_authenticity_not_guaranteed" = "The authenticity of this encrypted message can't be guaranteed on this device."; -"event_shield_reason_unknown_device" = "Encrypted by an unknown or deleted device."; -"event_shield_reason_unsigned_device" = "Encrypted by a device not verified by its owner."; -"event_shield_reason_unverified_identity" = "Encrypted by an unverified user."; +"event_shield_reason_authenticity_not_guaranteed" = "L'authenticitรฉ de ce message chiffrรฉ ne peut รชtre garantie sur cet appareil."; +"event_shield_reason_previously_verified" = "Chiffrรฉ par un utilisateur prรฉcรฉdemment vรฉrifiรฉ."; +"event_shield_reason_sent_in_clear" = "Non chiffrรฉ."; +"event_shield_reason_unknown_device" = "Chiffrรฉ par un appareil inconnu ou supprimรฉ."; +"event_shield_reason_unsigned_device" = "Chiffrรฉ par un appareil non vรฉrifiรฉ par son propriรฉtaire."; +"event_shield_reason_unverified_identity" = "Chiffrรฉ par un utilisateur non vรฉrifiรฉ."; "full_screen_intent_banner_message" = "Afin de ne jamais manquer un appel important, veuillez modifier vos paramรจtres pour autoriser les notifications en plein รฉcran lorsque votre appareil est verrouillรฉ."; "full_screen_intent_banner_title" = "Amรฉliorez votre expรฉrience d'appel"; "invite_friends_rich_title" = "๐Ÿ”๏ธ Rejoignez-moi sur %1$@"; @@ -275,11 +292,14 @@ "notification_inline_reply_failed" = "** ร‰chec de lโ€™envoi - veuillez ouvrir le salon"; "notification_invitation_action_reject" = "Rejeter"; "notification_invite_body" = "Vous a invitรฉ(e) ร  discuter"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "notification_mentioned_you_body" = "Mentionnรฉ(e): %1$@"; "notification_new_messages" = "Nouveaux messages"; "notification_reaction_body" = "A rรฉagi avec %1$@"; "notification_room_invite_body" = "Vous a invitรฉ(e) ร  rejoindre le salon"; +"notification_room_invite_body_with_sender" = "%1$@ invited you to join the room"; "notification_sender_me" = "Moi"; +"notification_sender_mention_reply" = "%1$@ mentionnรฉ ou en rรฉponse"; "notification_test_push_notification_content" = "Vous รชtes en train de voir la notificationย ! Cliquez-moiย !"; "notification_ticker_text_dm" = "%1$@ย : %2$@"; "notification_ticker_text_group" = "%1$@ย : %2$@ %3$@"; @@ -312,10 +332,27 @@ "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_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_pinned_timeline_screen_title_empty" = "Messages รฉpinglรฉs"; +"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."; +"screen_resolve_send_failure_changed_identity_primary_button_title" = "Rรฉvoquer la verification et envoyer"; +"screen_resolve_send_failure_changed_identity_subtitle" = "Vous pouvez rรฉvoquer la verification et envoyer ce message, ou vous pouvez annuler pour l'instant et rรฉessayer plus tard aprรจs avoir vรฉrifiรฉ ร  nouveau %1$@."; +"screen_resolve_send_failure_changed_identity_title" = "Votre message n'a pas รฉtรฉ envoyรฉ car l'identitรฉ vรฉrifiรฉe de %1$@ a changรฉ"; +"screen_resolve_send_failure_unsigned_device_primary_button_title" = "Envoyer le message quand mรชme"; +"screen_resolve_send_failure_unsigned_device_subtitle" = "%1$@ utilise un ou plusieurs appareils non vรฉrifiรฉs. Vous pouvez quand mรชme envoyer le message, ou vous pouvez annuler pour l'instant et rรฉessayer plus tard aprรจs que %2$@ vรฉrifie tous ses appareils."; +"screen_resolve_send_failure_unsigned_device_title" = "Votre message n'a pas รฉtรฉ envoyรฉ car %1$@ n'a pas vรฉrifiรฉ tous ses appareils"; +"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" = "Notifier tout le salon"; -"screen.room.pinned_banner_indicator" = "%1$@ of %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ Pinned messages"; -"screen.room.pinned_banner_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_details_pinned_events_row_title" = "Messages รฉpinglรฉs"; +"screen_timeline_item_menu_send_failure_changed_identity" = "Le message n'a pas รฉtรฉ envoyรฉ car l'identitรฉ vรฉrifiรฉe de %1$@ a changรฉ."; +"screen_timeline_item_menu_send_failure_unsigned_device" = "Le message n'a pas รฉtรฉ envoyรฉ car %1$@ n'a pas vรฉrifiรฉ tous ses appareils."; +"screen_timeline_item_menu_send_failure_you_unsigned_device" = "Message not sent because you have not verified one or more of your devices."; "screen_account_provider_change" = "Changer de fournisseur de compte"; "screen_account_provider_form_hint" = "Adresse du serveur dโ€™accueil"; "screen_account_provider_form_notice" = "Entrez un terme de recherche ou une adresse de domaine."; @@ -398,6 +435,7 @@ "screen_chat_backup_recovery_action_confirm_description" = "La sauvegarde des discussions est dรฉsynchronisรฉe."; "screen_chat_backup_recovery_action_setup" = "Configurer la rรฉcupรฉration"; "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"; "screen_create_new_recovery_key_list_item_2" = "Connectez-vous ร  nouveau ร  votre compte"; "screen_create_new_recovery_key_list_item_3" = "Lorsque vous devrez vรฉrifier la session, choisissez %1$@"; @@ -421,6 +459,17 @@ "screen_create_room_public_option_description" = "Les messages ne sont pas chiffrรฉs et nโ€™importe qui peut les lire. Vous pouvez activer le chiffrement ultรฉrieurement."; "screen_create_room_public_option_title" = "Salon public (tout le monde)"; "screen_create_room_topic_label" = "Sujet (facultatif)"; +"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_edit_poll_delete_confirmation" = "รŠtes-vous certain de vouloir supprimer ce sondage?"; "screen_edit_profile_display_name" = "Pseudonyme"; "screen_edit_profile_display_name_placeholder" = "Votre pseudonyme"; @@ -428,12 +477,20 @@ "screen_edit_profile_error_title" = "Impossible de mettre ร  jour le profil"; "screen_edit_profile_title" = "Modifier le profil"; "screen_edit_profile_updating_details" = "Mise ร  jour du profil..."; +"screen_encryption_reset_action_continue_reset" = "Continuer la rรฉinitialisation"; +"screen_encryption_reset_bullet_1" = "Les dรฉtails de votre compte, vos contacts, vos prรฉfรฉrences et votre liste de discussions seront conservรฉs"; +"screen_encryption_reset_bullet_2" = "Vous perdrez lโ€™historique de vos messages"; +"screen_encryption_reset_bullet_3" = "Vous devrez vรฉrifier ร  nouveau tous vos appareils et tous vos contacts"; +"screen_encryption_reset_footer" = "Ne rรฉinitialisez votre identitรฉ que si vous n'avez plus accรจs ร  aucune autre session et que vous avez perdu votre clรฉ de rรฉcupรฉration."; +"screen_encryption_reset_title" = "Can't confirm? Youโ€™ll need to reset your identity."; +"screen_identity_confirmation_cannot_confirm" = "Confirmation impossibleย ?"; "screen_identity_confirmation_create_new_recovery_key" = "Crรฉer une nouvelle clรฉ de rรฉcupรฉration"; "screen_identity_confirmation_subtitle" = "Vรฉrifier cette session pour configurer votre messagerie sรฉcurisรฉe."; "screen_identity_confirmation_title" = "Confirmez votre identitรฉ"; +"screen_identity_confirmation_use_another_device" = "Utiliser une autre session"; +"screen_identity_confirmation_use_recovery_key" = "Utiliser la clรฉ de rรฉcupรฉration"; "screen_identity_confirmed_subtitle" = "Vous pouvez dรฉsormais lire ou envoyer des messages en toute sรฉcuritรฉ, et toute personne avec qui vous discutez peut รฉgalement faire confiance ร  cette session."; "screen_identity_confirmed_title" = "Session vรฉrifiรฉe"; -"screen_identity_use_another_device" = "Utiliser une autre session"; "screen_identity_waiting_on_other_device" = "En attente dโ€™une autre sessionโ€ฆ"; "screen_invites_decline_chat_message" = "รŠtes-vous sรปr de vouloir dรฉcliner lโ€™invitation ร  rejoindre %1$@ย ?"; "screen_invites_decline_chat_title" = "Refuser lโ€™invitation"; @@ -556,7 +613,6 @@ "screen_recovery_key_confirm_error_content" = "Veuillez rรฉessayer afin de pouvoir accรฉder ร  vos anciens messages."; "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_label" = "Clรฉ de rรฉcupรฉration"; "screen_recovery_key_confirm_key_placeholder" = "Saisissez la clรฉ iciโ€ฆ"; "screen_recovery_key_confirm_lost_recovery_key" = "Clรฉ de rรฉcupรฉrationย perdue?"; "screen_recovery_key_confirm_success" = "Clรฉ de rรฉcupรฉration confirmรฉe"; @@ -577,6 +633,14 @@ "screen_report_content_block_user_hint" = "Cochez si vous souhaitez masquer tous les messages actuels et futurs de cet utilisateur."; "screen_report_content_explanation" = "Ce message sera signalรฉ ร  lโ€™administrateur de votre serveur dโ€™accueil. Il ne pourra lire aucun message chiffrรฉ."; "screen_report_content_hint" = "Raison du signalement de ce contenu"; +"screen_reset_encryption_confirmation_alert_action" = "Oui, rรฉinitialisez maintenant"; +"screen_reset_encryption_confirmation_alert_subtitle" = "Cette opรฉration ne peut pas รชtre annulรฉe."; +"screen_reset_encryption_confirmation_alert_title" = "Are you sure you want to reset your identity?"; +"screen_reset_encryption_password_placeholder" = "Saisissez..."; +"screen_reset_encryption_password_subtitle" = "Veuillez confirmer que vous souhaitez rรฉinitialiser votre identitรฉ."; +"screen_reset_encryption_password_title" = "Saisissez le mot de passe de votre compte pour continuer"; +"screen_reset_identity_confirmation_subtitle" = "Vous รชtes sur le point d'accรฉder ร  votre compte %1$@ pour rรฉinitialiser votre identitรฉ. Vous serez ensuite redirigรฉ vers l'application."; +"screen_reset_identity_confirmation_title" = "Vous ne pouvez pas confirmerย ? Accรฉdez ร  votre compte pour rรฉinitialiser votre identitรฉ."; "screen_room_alias_resolver_resolve_alias_failure" = "Impossible de trouver un salon avec cet alias."; "screen_room_attachment_source_camera" = "Appareil photo"; "screen_room_attachment_source_camera_video" = "Enregistrer une vidรฉo"; @@ -775,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "Avez-vous sauvegardรฉ votre clรฉ de rรฉcupรฉration?"; "screen_start_chat_error_starting_chat" = "Une erreur sโ€™est produite lors de la tentative de crรฉation de la discussion"; "screen_view_location_title" = "Position"; -"screen_waitlist_message" = "Il y a une forte demande pour %1$@ sur %2$@ ร  lโ€™heure actuelle. Revenez sur lโ€™application dans quelques jours et rรฉessayez. \n\nMerci pour votre patienceย !"; -"screen_waitlist_title" = "Vous y รชtes presque."; -"screen_waitlist_title_success" = "Vous y รชtes."; "screen_welcome_bullet_1" = "Les appels, les sondages, les recherches et plus encore seront ajoutรฉs plus tard cette annรฉe."; "screen_welcome_bullet_2" = "Lโ€™historique des messages pour les salons chiffrรฉs ne sera pas disponible dans cette mise ร  jour."; "screen_welcome_bullet_3" = "Nโ€™hรฉsitez pas ร  nous faire part de vos commentaires via lโ€™รฉcran des paramรจtres."; @@ -834,6 +895,12 @@ "state_event_room_name_removed_by_you" = "Vous avez supprimรฉ le nom du salon"; "state_event_room_none" = "%1$@ nโ€˜a fait aucun changement visible"; "state_event_room_none_by_you" = "Vous nโ€˜avez fait aucun changement visible"; +"state_event_room_pinned_events_changed" = "%1$@ a modifiรฉ les messages รฉpinglรฉs"; +"state_event_room_pinned_events_changed_by_you" = "Vous avez modifiรฉ les messages รฉpinglรฉs"; +"state_event_room_pinned_events_pinned" = "%1$@ a รฉpinglรฉ un message"; +"state_event_room_pinned_events_pinned_by_you" = "Vous avez รฉpinglรฉ un message"; +"state_event_room_pinned_events_unpinned" = "%1$@ a dรฉsรฉpinglรฉ un message"; +"state_event_room_pinned_events_unpinned_by_you" = "Vous avez dรฉsรฉpinglรฉ un message"; "state_event_room_reject" = "%1$@ a rejetรฉ lโ€™invitation"; "state_event_room_reject_by_you" = "Vous avez refusรฉ lโ€™invitation"; "state_event_room_remove" = "%1$@ a supprimรฉ %2$@"; @@ -921,6 +988,7 @@ "screen_dm_details_unblock_user" = "Dรฉbloquer lโ€™utilisateur"; "screen_edit_poll_delete_confirmation_title" = "Supprimer le sondage"; "screen_edit_poll_title" = "Modifier le sondage"; +"screen_identity_use_another_device" = "Utiliser une autre session"; "screen_login_subtitle" = "Matrix est un rรฉseau ouvert pour une communication sรฉcurisรฉe et dรฉcentralisรฉe."; "screen_qr_code_login_invalid_scan_state_retry_button" = "Essayer ร  nouveau"; "screen_report_content_block_user" = "Bloquer lโ€™utilisateur"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "Se dรฉconnecter"; "screen_signout_confirmation_dialog_title" = "Se dรฉconnecter"; "screen_signout_preference_item" = "Se dรฉconnecter"; -"screen_waitlist_message_success" = "Bienvenue dans %1$@ย !"; diff --git a/ElementX/Resources/Localizations/fr.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/fr.lproj/Localizable.stringsdict index 93306084a3..e456503941 100644 --- a/ElementX/Resources/Localizations/fr.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/fr.lproj/Localizable.stringsdict @@ -194,6 +194,22 @@ Code PIN incorrect. Il reste %1$d tentatives + screen_pinned_timeline_screen_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d message รฉpinglรฉ + other + %1$d messages รฉpinglรฉs + + screen_room_member_list_header_title NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/hu.lproj/Localizable.strings b/ElementX/Resources/Localizations/hu.lproj/Localizable.strings index c0e72cfcfc..e1cef07ed6 100644 --- a/ElementX/Resources/Localizations/hu.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/hu.lproj/Localizable.strings @@ -27,17 +27,20 @@ "action_back" = "Vissza"; "action_call" = "Hรญvรกs"; "action_cancel" = "Mรฉgse"; +"action_cancel_for_now" = "Egyelล‘re nem"; "action_choose_photo" = "Fรฉnykรฉp kivรกlasztรกsa"; "action_clear" = "Tรถrlรฉs"; "action_close" = "Bezรกrรกs"; "action_complete_verification" = "Ellenล‘rzรฉs befejezรฉse"; "action_confirm" = "Megerล‘sรญtรฉs"; +"action_confirm_password" = "Jelszรณ megerล‘sรญtรฉse"; "action_continue" = "Folytatรกs"; "action_copy" = "Mรกsolรกs"; "action_copy_link" = "Hivatkozรกs mรกsolรกsa"; "action_copy_link_to_message" = "รœzenetre mutatรณ hivatkozรกs mรกsolรกsa"; "action_create" = "Lรฉtrehozรกs"; "action_create_a_room" = "Szoba lรฉtrehozรกsa"; +"action_deactivate" = "Deaktivรกlรกs"; "action_decline" = "Elutasรญtรกs"; "action_delete_poll" = "Szavazรกs tรถrlรฉse"; "action_disable" = "Letiltรกs"; @@ -70,6 +73,7 @@ "action_ok" = "Rendben"; "action_open_settings" = "Beรกllรญtรกsok megnyitรกsa"; "action_open_with" = "Megnyitรกs a kรถvetkezล‘vel"; +"action_pin" = "Kitลฑzรฉs"; "action_quick_reply" = "Gyors vรกlasz"; "action_quote" = "Idรฉzet"; "action_react" = "Reakciรณ"; @@ -80,6 +84,7 @@ "action_report_bug" = "Hiba jelentรฉse"; "action_report_content" = "Tartalom jelentรฉse"; "action_reset" = "Visszaรกllรญtรกs"; +"action_reset_identity" = "Szemรฉlyazonossรกg visszaรกllรญtรกsa"; "action_retry" = "รšjra"; "action_retry_decryption" = "Visszafejtรฉs รบjbรณli megprรณbรกlรกsa"; "action_save" = "Mentรฉs"; @@ -99,10 +104,18 @@ "action_take_photo" = "Fรฉnykรฉp kรฉszรญtรฉse"; "action_tap_for_options" = "Koppintson a beรกllรญtรกsokรฉrt"; "action_try_again" = "Prรณbรกlja รบjra"; +"action_unpin" = "Kitลฑzรฉs feloldรกsa"; +"action_view_in_timeline" = "Megtekintรฉs az idล‘vonalon"; "action_view_source" = "Forrรกs megtekintรฉse"; "action_yes" = "Igen"; "action.load_more" = "Tovรกbbiak betรถltรฉse"; -"action.pin" = "Kitลฑzรฉs"; +"action_deactivate_account" = "Fiรณk deaktivรกlรกsa"; +"banner_migrate_to_native_sliding_sync_action" = "Kijelentkezรฉs รฉs frissรญtรฉs"; +"banner_migrate_to_native_sliding_sync_description" = "A kiszolgรกlรณja mostantรณl egy รบj, gyorsabb protokollt tรกmogat. A frissรญtรฉshez jelentkezzen ki, majd jelentkezzen be รบjra. Ha ezt most megteszi, elkerรผlheti a kรฉnyszerรญtett kijelentkeztetรฉst a rรฉgi protokollt eltรกvolรญtรกsakor."; +"banner_migrate_to_native_sliding_sync_force_logout_title" = "A Matrix-kiszolgรกlรณ mรกr nem tรกmogatja a rรฉgi protokollt. Az alkalmazรกs tovรกbbi hasznรกlatรกhoz jelentkezzen ki รฉs be."; +"banner_migrate_to_native_sliding_sync_title" = "Frissรญtรฉs รฉrhetล‘ el"; +"banner.set_up_recovery.content" = "Hozzon lรฉtre egy รบj helyreรกllรญtรกsi kulcsot, amellyel visszaรกllรญthatja a titkosรญtott รผzenetek elล‘zmรฉnyeit, ha elveszรญti az eszkรถzรถkhรถz valรณ hozzรกfรฉrรฉst."; +"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_advanced_settings" = "Speciรกlis beรกllรญtรกsok"; @@ -214,6 +227,7 @@ "common_waiting_for_decryption_key" = "Vรกrakozรกs a visszafejtรฉsi kulcsra"; "common.do_not_show_this_again" = "Ne jelenjen meg tรถbbรฉ"; "common.open_source_licenses" = "Nyรญlt forrรกskรณdรบ licencek"; +"common.pinned" = "Kitลฑzve"; "common.send_to" = "Cรญmzett"; "common_no_room_name" = "Nincs szobanรฉv"; "common_poll_end_confirmation" = "Biztos, hogy befejezi ezt a szavazรกst?"; @@ -244,6 +258,7 @@ "emoji_picker_category_people" = "Mosolyok รฉs emberek"; "emoji_picker_category_places" = "Utazรกs รฉs helyek"; "emoji_picker_category_symbols" = "Szimbรณlumok"; +"error_account_creation_not_possible" = "A Matrix-kiszolgรกlรณt frissรญteni kell a Matrix Authentication Service รฉs a fiรณklรฉtrehozรกs tรกmogatรกsรกhoz."; "error_failed_creating_the_permalink" = "Nem sikerรผlt lรฉtrehozni az รกllandรณ hivatkozรกst"; "error_failed_loading_map" = "Az %1$@ nem tudta betรถlteni a tรฉrkรฉpet. Prรณbรกlja meg รบjra kรฉsล‘bb."; "error_failed_loading_messages" = "Nem sikerรผlt betรถlteni az รผzeneteket"; @@ -254,6 +269,8 @@ "error_some_messages_have_not_been_sent" = "Nรฉhรกny รผzenet nem kerรผlt elkรผldรฉsre"; "error_unknown" = "Elnรฉzรฉst, hiba tรถrtรฉnt"; "event_shield_reason_authenticity_not_guaranteed" = "A titkosรญtott รผzenetek valรณdisรกgรกt ezen az eszkรถzรถn nem lehet garantรกlni."; +"event_shield_reason_previously_verified" = "Egy korรกbban ellenล‘rzรถtt felhasznรกlรณ รกltal titkosรญtva."; +"event_shield_reason_sent_in_clear" = "Nincs titkosรญtva."; "event_shield_reason_unknown_device" = "Ismeretlen vagy tรถrรถlt eszkรถz รกltal titkosรญtva."; "event_shield_reason_unsigned_device" = "A tulajdonos รกltal nem ellenล‘rzรถtt eszkรถz รกltal titkosรญtva."; "event_shield_reason_unverified_identity" = "Nem ellenล‘rzรถtt felhasznรกlรณ รกltal titkosรญtva."; @@ -275,11 +292,14 @@ "notification_inline_reply_failed" = "** Nem sikerรผlt elkรผldeni โ€“ nyissa meg a szobรกt"; "notification_invitation_action_reject" = "Elutasรญtรกs"; "notification_invite_body" = "Meghรญvta, hogy csevegjen"; +"notification_invite_body_with_sender" = "%1$@ meghรญvta egy csevegรฉsre"; "notification_mentioned_you_body" = "Megemlรญtette ร–nt: %1$@"; "notification_new_messages" = "รšj รผzenetek"; "notification_reaction_body" = "Ezzel reagรกlt: %1$@"; "notification_room_invite_body" = "Meghรญvta, hogy csatlakozzon a szobรกhoz"; +"notification_room_invite_body_with_sender" = "%1$@ meghรญvta, hogy csatlakozzon a szobรกhoz"; "notification_sender_me" = "ร‰n"; +"notification_sender_mention_reply" = "%1$@ megemlรญtette vagy vรกlaszolt"; "notification_test_push_notification_content" = "Az รฉrtesรญtรฉst nรฉzi! Kattintson ide!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -312,10 +332,27 @@ "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_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_pinned_timeline_screen_title_empty" = "Kitลฑzรถtt รผzenetek"; +"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."; +"screen_resolve_send_failure_changed_identity_primary_button_title" = "Ellenล‘rzรฉs visszavonรกsa รฉs elkรผldรฉs"; +"screen_resolve_send_failure_changed_identity_subtitle" = "Visszavonhatja az ellenล‘rzรฉst, รฉs ennek ellenรฉre elkรผldheti ezt az รผzenetet, vagy egyelล‘re tรถrรถlheti, รฉs %1$@ รบjbรณli ellenล‘rzรฉse utรกn รบjra megprรณbรกlhatja."; +"screen_resolve_send_failure_changed_identity_title" = "Az รผzenete nem lett elkรผldve, mert %1$@ ellenล‘rzรถtt szemรฉlyazonossรกga megvรกltozott."; +"screen_resolve_send_failure_unsigned_device_primary_button_title" = "รœzenet elkรผldรฉse mindenkรฉpp"; +"screen_resolve_send_failure_unsigned_device_subtitle" = "%1$@ egy vagy tรถbb ellenล‘rizetlen eszkรถzt hasznรกl. รgy is elkรผldheti az รผzenetet, vagy megszakรญthatja most, รฉs megprรณbรกlhatja รบjra, miutรกn %2$@ ellenล‘rizte az รถsszes eszkรถzรฉt."; +"screen_resolve_send_failure_unsigned_device_title" = "Az รผzenet nem lett elkรผldve, mert %1$@ nem ellenล‘rizte az รถsszes eszkรถzรฉt"; +"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.pinned_banner_indicator" = "%1$@ of %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ Pinned messages"; -"screen.room.pinned_banner_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_details_pinned_events_row_title" = "Kitลฑzรถtt รผzenetek"; +"screen_timeline_item_menu_send_failure_changed_identity" = "Az รผzenet nem lett elkรผldve, mert %1$@ ellenล‘rzรถtt szemรฉlyazonossรกga megvรกltozott."; +"screen_timeline_item_menu_send_failure_unsigned_device" = "Az รผzenet nem lett elkรผldve, mert %1$@ nem ellenล‘rizte az รถsszes eszkรถzรฉt."; +"screen_timeline_item_menu_send_failure_you_unsigned_device" = "Az รผzenet nem lett elkรผldve, mert egy vagy tรถbb eszkรถzรฉt nem ellenล‘rizte."; "screen_account_provider_change" = "Fiรณkszolgรกltatรณ mรณdosรญtรกsa"; "screen_account_provider_form_hint" = "Matrix-kiszolgรกlรณ webcรญme"; "screen_account_provider_form_notice" = "Adjon meg egy keresรฉsi kifejezรฉst vagy egy tartomรกnycรญmet."; @@ -398,6 +435,7 @@ "screen_chat_backup_recovery_action_confirm_description" = "A csevegรฉselล‘zmรฉnyei nincsenek szinkronban."; "screen_chat_backup_recovery_action_setup" = "Helyreรกllรญtรกs beรกllรญtรกsa"; "screen_chat_backup_recovery_action_setup_description" = "Szerezzen hozzรกfรฉrรฉst a titkosรญtott รผzeneteihez, ha elvesztette az รถsszes eszkรถzรฉt, vagy ha mindenรผtt kijelentkezett az %1$@bล‘l."; +"screen_create_account_title" = "Fiรณk lรฉtrehozรกsa"; "screen_create_new_recovery_key_list_item_1" = "Nyissa meg az %1$@et egy asztali eszkรถzรถn"; "screen_create_new_recovery_key_list_item_2" = "Jelentkezzen be รบjra a fiรณkjรกba"; "screen_create_new_recovery_key_list_item_3" = "Amikor az eszkรถz ellenล‘rzรฉsรฉt kรฉri, vรกlassza ezt a lehetล‘sรฉget: %1$@"; @@ -421,6 +459,17 @@ "screen_create_room_public_option_description" = "Az รผzenetek nincsenek titkosรญtva, รฉs bรกrki elolvashatja ล‘ket. A titkosรญtรกst kรฉsล‘bb is engedรฉlyezheti."; "screen_create_room_public_option_title" = "Nyilvรกnos szoba (bรกrki)"; "screen_create_room_topic_label" = "Tรฉma (nem kรถtelezล‘)"; +"screen_deactivate_account_confirmation_dialog_content" = "Erล‘sรญtse meg, hogy deaktivรกlja a fiรณkjรกt. Ez a mลฑvelet nem vonhatรณ vissza."; +"screen_deactivate_account_delete_all_messages" = "ร–sszes sajรกt รผzenet tรถrlรฉse"; +"screen_deactivate_account_delete_all_messages_notice" = "Figyelmeztetรฉs: A jรถvล‘beli felhasznรกlรณk hiรกnyos beszรฉlgetรฉseket lรกthatnak."; +"screen_deactivate_account_description" = "A fiรณk deaktivรกlรกsa %1$@, a kรถvetkezล‘ket okozza:"; +"screen_deactivate_account_description_bold_part" = "visszafordรญthatatlan"; +"screen_deactivate_account_list_item_1" = "%1$@ a fiรณkjรกt (nem fog tudni รบjra bejelentkezni, รฉs az azonosรญtรณja nem hasznรกlhatรณ รบjra)."; +"screen_deactivate_account_list_item_1_bold_part" = "Vรฉglegesen letiltja"; +"screen_deactivate_account_list_item_2" = "Eltรกvolรญtรกsra kerรผl az รถsszes csevegล‘szobรกbรณl."; +"screen_deactivate_account_list_item_3" = "Tรถrlรฉsre kerรผlnek a fiรณkadatai a szemรฉlyazonosรญtรณ kiszolgรกlรณnkrรณl."; +"screen_deactivate_account_list_item_4" = "รœzenetei tovรกbbra is lรกthatรณak maradnak a regisztrรกlt felhasznรกlรณk szรกmรกra, de nem lesznek elรฉrhetล‘ek az รบj vagy nem regisztrรกlt felhasznรกlรณk szรกmรกra, ha รบgy dรถnt, hogy tรถrli ล‘ket."; +"screen_deactivate_account_title" = "Fiรณk deaktivรกlรกsa"; "screen_edit_poll_delete_confirmation" = "Biztos, hogy tรถrli ezt a szavazรกst?"; "screen_edit_profile_display_name" = "Megjelenรญtendล‘ nรฉv"; "screen_edit_profile_display_name_placeholder" = "Sajรกt megjelenรญtendล‘ nรฉv"; @@ -428,12 +477,20 @@ "screen_edit_profile_error_title" = "Nem sikerรผlt frissรญteni a profilt"; "screen_edit_profile_title" = "Profil szerkesztรฉse"; "screen_edit_profile_updating_details" = "Profil frissรญtรฉseโ€ฆ"; +"screen_encryption_reset_action_continue_reset" = "Visszaรกllรญtรกs folytatรกsa"; +"screen_encryption_reset_bullet_1" = "A fiรณkadatok, a kapcsolatok, a beรกllรญtรกsok รฉs a csevegรฉslista megmarad"; +"screen_encryption_reset_bullet_2" = "Elveszรญti meglรฉvล‘ รผzenetelล‘zmรฉnyeit"; +"screen_encryption_reset_bullet_3" = "รšjbรณl ellenล‘riznie kell az รถsszes meglรฉvล‘ eszkรถzรฉt รฉs csevegล‘partnerรฉt"; +"screen_encryption_reset_footer" = "Csak akkor รกllรญtsa vissza a szemรฉlyazonossรกgรกt, ha nem fรฉr hozzรก mรกsik bejelentkezett eszkรถzhรถz, รฉs elvesztette a helyreรกllรญtรกsi kulcsot."; +"screen_encryption_reset_title" = "รllรญtsa vissza a szemรฉlyazonossรกgรกt, ha mรกs mรณdon nem tudja megerล‘sรญteni"; +"screen_identity_confirmation_cannot_confirm" = "Nem tudja megerล‘sรญteni?"; "screen_identity_confirmation_create_new_recovery_key" = "รšj helyreรกllรญtรกsi kulcs lรฉtrehozรกsa"; "screen_identity_confirmation_subtitle" = "A biztonsรกgos รผzenetkezelรฉs beรกllรญtรกsรกhoz ellenล‘rizze ezt az eszkรถzt."; "screen_identity_confirmation_title" = "Erล‘sรญtse meg, hogy ร–n az"; +"screen_identity_confirmation_use_another_device" = "Mรกsik eszkรถz hasznรกlata"; +"screen_identity_confirmation_use_recovery_key" = "Helyreรกllรญtรกsi kulcs hasznรกlata"; "screen_identity_confirmed_subtitle" = "Mostantรณl biztonsรกgosan olvashat vagy kรผldhet รผzeneteket, รฉs bรกrmelyik csevegล‘partnere megbรญzhat ebben az eszkรถzben."; "screen_identity_confirmed_title" = "Eszkรถz ellenล‘rizve"; -"screen_identity_use_another_device" = "Mรกsik eszkรถz hasznรกlata"; "screen_identity_waiting_on_other_device" = "Vรกrakozรกs a mรกsik eszkรถzreโ€ฆ"; "screen_invites_decline_chat_message" = "Biztos, hogy elutasรญtja a meghรญvรกst, hogy csatlakozzon ehhez: %1$@?"; "screen_invites_decline_chat_title" = "Meghรญvรกs elutasรญtรกsa"; @@ -556,7 +613,6 @@ "screen_recovery_key_confirm_error_content" = "Prรณbรกlja meg รบjra megerล‘sรญteni a csevegรฉs biztonsรกgi mentรฉsรฉhez valรณ hozzรกfรฉrรฉsรฉt."; "screen_recovery_key_confirm_error_title" = "Helytelen helyreรกllรญtรกsi kulcs"; "screen_recovery_key_confirm_key_description" = "Ha van biztonsรกgi kulcsa vagy biztonsรกgi jelmondata, akkor ez is fog mลฑkรถdni."; -"screen_recovery_key_confirm_key_label" = "Helyreรกllรญtรกsi kulcs vagy jelkรณd"; "screen_recovery_key_confirm_key_placeholder" = "Megadรกsโ€ฆ"; "screen_recovery_key_confirm_lost_recovery_key" = "Elvesztette a helyreรกllรญtรกsi kulcsรกt?"; "screen_recovery_key_confirm_success" = "Helyreรกllรญtรกsi kulcs megerล‘sรญtve"; @@ -577,6 +633,14 @@ "screen_report_content_block_user_hint" = "Jelรถlje be, ha el akarja rejteni az รถsszes jelenlegi รฉs jรถvล‘beli รผzenetet ettล‘l a felhasznรกlรณtรณl"; "screen_report_content_explanation" = "Ez az รผzenet jelentve lesz a Matrix-kiszolgรกlรณ adminisztrรกtorรกnak. Nem fogja tudni elolvasni a titkosรญtott รผzeneteket."; "screen_report_content_hint" = "A tartalom jelentรฉsรฉnek oka"; +"screen_reset_encryption_confirmation_alert_action" = "Igen, visszaรกllรญtรกs most"; +"screen_reset_encryption_confirmation_alert_subtitle" = "Ez a folyamat visszafordรญthatatlan."; +"screen_reset_encryption_confirmation_alert_title" = "Biztos, hogy visszaรกllรญtja a titkosรญtรกst?"; +"screen_reset_encryption_password_placeholder" = "Adja megโ€ฆ"; +"screen_reset_encryption_password_subtitle" = "Erล‘sรญtse meg, hogy vissza szeretnรฉ รกllรญtani a titkosรญtรกst."; +"screen_reset_encryption_password_title" = "A folytatรกshoz adja meg fiรณkja jelszavรกt"; +"screen_reset_identity_confirmation_subtitle" = "Arra kรฉszรผl, hogy belรฉpjen a(z) %1$@ fiรณkjรกba, hogy visszaรกllรญtsa a szemรฉlyazonossรกgรกt. Ezutรกn vissza fog tรฉrni az alkalmazรกsba."; +"screen_reset_identity_confirmation_title" = "Nem tudja megerล‘sรญteni? Ugorjon a fiรณkjรกhoz, รฉs รกllรญtsa vissza a szemรฉlyazonossรกgรกt."; "screen_room_alias_resolver_resolve_alias_failure" = "Nem sikerรผlt a szoba รกlnevรฉnek feloldรกsa."; "screen_room_attachment_source_camera" = "Kamera"; "screen_room_attachment_source_camera_video" = "Videรณ rรถgzรญtรฉse"; @@ -775,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "Mentette a helyreรกllรญtรกsi kulcsรกt?"; "screen_start_chat_error_starting_chat" = "Hiba tรถrtรฉnt a csevegรฉs indรญtรกsakor"; "screen_view_location_title" = "Hely"; -"screen_waitlist_message" = "Jelenleg nagy a kereslet a(z) %2$@ oldalon futรณ %1$@ irรกnt. Tรฉrjen vissza nรฉhรกny nap mรบlva az alkalmazรกshoz, รฉs prรณbรกlja รบjra.\n\nKรถszรถnjรผk a tรผrelmรฉt!"; -"screen_waitlist_title" = "Mรกr majdnem kรฉsz van."; -"screen_waitlist_title_success" = "Bent van."; "screen_welcome_bullet_1" = "A hรญvรกsok, szavazรกsok, keresรฉsek รฉs egyebek az รฉv tovรกbbi rรฉszรฉben kerรผlnek hozzรกadรกsra."; "screen_welcome_bullet_2" = "A titkosรญtott szobรกk รผzenetelล‘zmรฉnyei nem lesznek elรฉrhetล‘k ebben a frissรญtรฉsben."; "screen_welcome_bullet_3" = "Szeretnรฉnk hallani a vรฉlemรฉnyรฉt, ossza meg velรผnk a beรกllรญtรกsok oldalon."; @@ -834,6 +895,12 @@ "state_event_room_name_removed_by_you" = "Eltรกvolรญtotta a szoba nevรฉt"; "state_event_room_none" = "%1$@ nem vรกltoztatott semmin"; "state_event_room_none_by_you" = "Nem vรกltoztatott semmin"; +"state_event_room_pinned_events_changed" = "%1$@ megvรกltoztatta a kitลฑzรถtt รผzeneteket"; +"state_event_room_pinned_events_changed_by_you" = "Megvรกltoztatta a kitลฑzรถtt รผzeneteket"; +"state_event_room_pinned_events_pinned" = "%1$@ kitลฑzรถtt egy รผzenetet"; +"state_event_room_pinned_events_pinned_by_you" = "Kitลฑzรถtt egy รผzenetet"; +"state_event_room_pinned_events_unpinned" = "%1$@ feloldotta egy รผzenet kitลฑzรฉsรฉt"; +"state_event_room_pinned_events_unpinned_by_you" = "Feloldotta egy รผzenet kitลฑzรฉsรฉt"; "state_event_room_reject" = "%1$@ elutasรญtotta a meghรญvรกst"; "state_event_room_reject_by_you" = "Elutasรญtotta a meghรญvรกst"; "state_event_room_remove" = "%1$@ eltรกvolรญtotta: %2$@"; @@ -921,6 +988,7 @@ "screen_dm_details_unblock_user" = "Felhasznรกlรณ kitiltรกsรกnak feloldรกsa"; "screen_edit_poll_delete_confirmation_title" = "Szavazรกs tรถrlรฉse"; "screen_edit_poll_title" = "Szavazรกs szerkesztรฉse"; +"screen_identity_use_another_device" = "Mรกsik eszkรถz hasznรกlata"; "screen_login_subtitle" = "A Matrix egy nyitott hรกlรณzat a biztonsรกgos, decentralizรกlt kommunikรกciรณhoz."; "screen_qr_code_login_invalid_scan_state_retry_button" = "Prรณbรกlja รบjra"; "screen_report_content_block_user" = "Felhasznรกlรณ letiltรกsa"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "Kijelentkezรฉs"; "screen_signout_confirmation_dialog_title" = "Kijelentkezรฉs"; "screen_signout_preference_item" = "Kijelentkezรฉs"; -"screen_waitlist_message_success" = "รœdvรถzli az %1$@!"; diff --git a/ElementX/Resources/Localizations/hu.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/hu.lproj/Localizable.stringsdict index 41b6cf02c8..8830225081 100644 --- a/ElementX/Resources/Localizations/hu.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/hu.lproj/Localizable.stringsdict @@ -194,6 +194,22 @@ Hibรกs PIN-kรณd. Mรฉg %1$d prรณbรกlkozรกsi lehetล‘sรฉge maradt. + screen_pinned_timeline_screen_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d kitลฑzรถtt รผzenet + other + %1$d kitลฑzรถtt รผzenet + + screen_room_member_list_header_title NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/id.lproj/Localizable.strings b/ElementX/Resources/Localizations/id.lproj/Localizable.strings index 5dcd8a6b0c..2712368036 100644 --- a/ElementX/Resources/Localizations/id.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/id.lproj/Localizable.strings @@ -27,17 +27,20 @@ "action_back" = "Kembali"; "action_call" = "Panggil"; "action_cancel" = "Batal"; +"action_cancel_for_now" = "Cancel for now"; "action_choose_photo" = "Pilih foto"; "action_clear" = "Hapus"; "action_close" = "Tutup"; "action_complete_verification" = "Selesaikan verifikasi"; "action_confirm" = "Konfirmasi"; +"action_confirm_password" = "Confirm password"; "action_continue" = "Lanjutkan"; "action_copy" = "Salin"; "action_copy_link" = "Salin tautan"; "action_copy_link_to_message" = "Salin tautan ke pesan"; "action_create" = "Buat"; "action_create_a_room" = "Buat ruangan"; +"action_deactivate" = "Deactivate"; "action_decline" = "Tolak"; "action_delete_poll" = "Hapus pemungutan suara"; "action_disable" = "Nonaktifkan"; @@ -70,6 +73,7 @@ "action_ok" = "Oke"; "action_open_settings" = "Pengaturan"; "action_open_with" = "Buka dengan"; +"action_pin" = "Pin"; "action_quick_reply" = "Balas cepat"; "action_quote" = "Kutip"; "action_react" = "Bereaksi"; @@ -80,6 +84,7 @@ "action_report_bug" = "Laporkan kutu"; "action_report_content" = "Laporkan Konten"; "action_reset" = "Atur ulang"; +"action_reset_identity" = "Reset identity"; "action_retry" = "Coba lagi"; "action_retry_decryption" = "Coba dekripsi ulang"; "action_save" = "Simpan"; @@ -99,10 +104,18 @@ "action_take_photo" = "Ambil foto"; "action_tap_for_options" = "Ketuk untuk opsi"; "action_try_again" = "Coba lagi"; +"action_unpin" = "Unpin"; +"action_view_in_timeline" = "View in timeline"; "action_view_source" = "Tampilkan sumber"; "action_yes" = "Ya"; "action.load_more" = "Muat lainnya"; -"action.pin" = "Pin"; +"action_deactivate_account" = "Deactivate account"; +"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" = "Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices."; +"banner.set_up_recovery.title" = "Set up recovery"; "common_about" = "Tentang"; "common_acceptable_use_policy" = "Kebijakan penggunaan wajar"; "common_advanced_settings" = "Pengaturan tingkat lanjut"; @@ -214,6 +227,7 @@ "common_waiting_for_decryption_key" = "Menunggu pesan ini"; "common.do_not_show_this_again" = "Jangan tampilkan ini lagi"; "common.open_source_licenses" = "Open source licenses"; +"common.pinned" = "Pinned"; "common.send_to" = "Kirim ke"; "common_no_room_name" = "Tidak ada nama ruangan"; "common_poll_end_confirmation" = "Apakah Anda yakin ingin mengakhiri pemungutan suara ini?"; @@ -244,6 +258,7 @@ "emoji_picker_category_people" = "Senyuman & Orang"; "emoji_picker_category_places" = "Wisata & Tempat"; "emoji_picker_category_symbols" = "Simbol"; +"error_account_creation_not_possible" = "Your homeserver needs to be upgraded to support Matrix Authentication Service and account creation."; "error_failed_creating_the_permalink" = "Gagal membuat tautan permanen"; "error_failed_loading_map" = "%1$@ tidak dapat memuat peta. Silakan coba lagi nanti."; "error_failed_loading_messages" = "Gagal memuat pesan"; @@ -254,6 +269,8 @@ "error_some_messages_have_not_been_sent" = "Beberapa pesan belum terkirim"; "error_unknown" = "Maaf, terjadi kesalahan"; "event_shield_reason_authenticity_not_guaranteed" = "The authenticity of this encrypted message can't be guaranteed on this device."; +"event_shield_reason_previously_verified" = "Encrypted by a previously-verified user."; +"event_shield_reason_sent_in_clear" = "Not encrypted."; "event_shield_reason_unknown_device" = "Encrypted by an unknown or deleted device."; "event_shield_reason_unsigned_device" = "Encrypted by a device not verified by its owner."; "event_shield_reason_unverified_identity" = "Encrypted by an unverified user."; @@ -275,11 +292,14 @@ "notification_inline_reply_failed" = "** Gagal mengirim โ€” silakan buka ruangan"; "notification_invitation_action_reject" = "Tolak"; "notification_invite_body" = "Mengundang Anda untuk mengobrol"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "notification_mentioned_you_body" = "Menyebutkan Anda: %1$@"; "notification_new_messages" = "Pesan Baru"; "notification_reaction_body" = "Menghapus dengan %1$@"; "notification_room_invite_body" = "Mengundang Anda untuk bergabung ke ruangan"; +"notification_room_invite_body_with_sender" = "%1$@ invited you to join the room"; "notification_sender_me" = "Saya"; +"notification_sender_mention_reply" = "%1$@ mentioned or replied"; "notification_test_push_notification_content" = "Anda sedang melihat pemberitahuan ini! Klik saya!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -312,10 +332,27 @@ "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_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_pinned_timeline_screen_title_empty" = "Pinned messages"; +"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" = "Beri tahu seluruh ruangan"; -"screen.room.pinned_banner_indicator" = "%1$@ of %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ Pinned messages"; -"screen.room.pinned_banner_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_details_pinned_events_row_title" = "Pinned messages"; +"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_account_provider_change" = "Ubah penyedia akun"; "screen_account_provider_form_hint" = "Alamat homeserver"; "screen_account_provider_form_notice" = "Masukkan istilah pencarian atau alamat domain."; @@ -398,6 +435,7 @@ "screen_chat_backup_recovery_action_confirm_description" = "Pencadangan percakapan Anda saat ini tidak tersinkron."; "screen_chat_backup_recovery_action_setup" = "Siapkan pemulihan"; "screen_chat_backup_recovery_action_setup_description" = "Dapatkan akses ke pesan terenkripsi Anda jika Anda kehilangan semua perangkat Anda atau keluar dari %1$@ di mana pun."; +"screen_create_account_title" = "Create account"; "screen_create_new_recovery_key_list_item_1" = "Buka %1$@ di perangkat desktop"; "screen_create_new_recovery_key_list_item_2" = "Masuk ke akun Anda lagi"; "screen_create_new_recovery_key_list_item_3" = "Saat diminta untuk memverifikasi perangkat Anda, pilih %1$@"; @@ -421,6 +459,17 @@ "screen_create_room_public_option_description" = "Pesan tidak dienkripsi dan siapa pun dapat membacanya. Anda dapat mengaktifkan enkripsi di kemudian hari."; "screen_create_room_public_option_title" = "Ruang publik (siapa saja)"; "screen_create_room_topic_label" = "Topik (opsional)"; +"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_edit_poll_delete_confirmation" = "Apakah Anda yakin ingin menghapus pemungutan suara ini?"; "screen_edit_profile_display_name" = "Nama tampilan"; "screen_edit_profile_display_name_placeholder" = "Nama tampilan Anda"; @@ -428,12 +477,20 @@ "screen_edit_profile_error_title" = "Tidak dapat memperbarui profil"; "screen_edit_profile_title" = "Sunting profil"; "screen_edit_profile_updating_details" = "Memperbarui profilโ€ฆ"; +"screen_encryption_reset_action_continue_reset" = "Continue reset"; +"screen_encryption_reset_bullet_1" = "Your account details, contacts, preferences, and chat list will be kept"; +"screen_encryption_reset_bullet_2" = "You will lose your existing message history"; +"screen_encryption_reset_bullet_3" = "You will need to verify all your existing devices and contacts again"; +"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_identity_confirmation_create_new_recovery_key" = "Buat kunci pemulihan baru"; "screen_identity_confirmation_subtitle" = "Verifikasi perangkat ini untuk menyiapkan perpesanan aman."; "screen_identity_confirmation_title" = "Konfirmasi bahwa ini Anda"; +"screen_identity_confirmation_use_another_device" = "Gunakan perangkat lain"; +"screen_identity_confirmation_use_recovery_key" = "Use recovery key"; "screen_identity_confirmed_subtitle" = "Sekarang Anda dapat membaca atau mengirim pesan dengan aman, dan siapa pun yang mengobrol dengan Anda juga dapat mempercayai perangkat ini."; "screen_identity_confirmed_title" = "Perangkat terverifikasi"; -"screen_identity_use_another_device" = "Gunakan perangkat lain"; "screen_identity_waiting_on_other_device" = "Menunggu di perangkat lainโ€ฆ"; "screen_invites_decline_chat_message" = "Apakah Anda yakin ingin menolak undangan untuk bergabung ke %1$@?"; "screen_invites_decline_chat_title" = "Tolak undangan"; @@ -556,7 +613,6 @@ "screen_recovery_key_confirm_error_content" = "Silakan coba lagi untuk mengonfirmasi akses ke cadangan percakapan Anda."; "screen_recovery_key_confirm_error_title" = "Kunci pemulihan salah"; "screen_recovery_key_confirm_key_description" = "Jika Anda memiliki kunci keamanan atau frasa keamanan, ini juga bisa digunakan."; -"screen_recovery_key_confirm_key_label" = "Kunci pemulihan atau kode sandi"; "screen_recovery_key_confirm_key_placeholder" = "Masukkan..."; "screen_recovery_key_confirm_lost_recovery_key" = "Kehilangan kunci pemulihan Anda?"; "screen_recovery_key_confirm_success" = "Kunci pemulihan dikonfirmasi"; @@ -577,6 +633,14 @@ "screen_report_content_block_user_hint" = "Centang jika Anda ingin menyembunyikan semua pesan saat ini dan yang akan datang dari pengguna ini"; "screen_report_content_explanation" = "Pesan ini akan dilaporkan ke administrator homeserver Anda. Mereka tidak akan dapat membaca pesan terenkripsi apa pun."; "screen_report_content_hint" = "Alasan melaporkan konten ini"; +"screen_reset_encryption_confirmation_alert_action" = "Yes, reset now"; +"screen_reset_encryption_confirmation_alert_subtitle" = "This process is irreversible."; +"screen_reset_encryption_confirmation_alert_title" = "Are you sure you want to reset your identity?"; +"screen_reset_encryption_password_placeholder" = "Enterโ€ฆ"; +"screen_reset_encryption_password_subtitle" = "Confirm that you want to reset your identity."; +"screen_reset_encryption_password_title" = "Enter your account password to continue"; +"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_room_alias_resolver_resolve_alias_failure" = "Gagal menyelesaikan alias ruangan."; "screen_room_attachment_source_camera" = "Kamera"; "screen_room_attachment_source_camera_video" = "Rekam video"; @@ -775,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "Apakah Anda sudah menyimpan kunci pemulihan Anda?"; "screen_start_chat_error_starting_chat" = "Terjadi kesalahan saat mencoba memulai obrolan"; "screen_view_location_title" = "Lokasi"; -"screen_waitlist_message" = "Ada permintaan tinggi untuk %1$@ di %2$@ saat ini. Kembalilah ke aplikasi dalam beberapa hari dan coba lagi.\n\nTerima kasih atas kesabaran Anda!"; -"screen_waitlist_title" = "Anda hampir selesai."; -"screen_waitlist_title_success" = "Anda sudah masuk."; "screen_welcome_bullet_1" = "Panggilan, pemungutan suara, pencarian, dan lainnya akan ditambahkan di tahun ini."; "screen_welcome_bullet_2" = "Riwayat pesan untuk ruangan terenkripsi tidak akan tersedia dalam pembaruan ini."; "screen_welcome_bullet_3" = "Kami ingin mendengar dari Anda, beri tahu kami pendapat Anda melalui halaman pengaturan."; @@ -834,6 +895,12 @@ "state_event_room_name_removed_by_you" = "Anda menghapus nama ruangan"; "state_event_room_none" = "%1$@ tidak membuat perubahan"; "state_event_room_none_by_you" = "Anda tidak membuat perubahan"; +"state_event_room_pinned_events_changed" = "%1$@ changed the pinned messages"; +"state_event_room_pinned_events_changed_by_you" = "You changed the pinned messages"; +"state_event_room_pinned_events_pinned" = "%1$@ pinned a message"; +"state_event_room_pinned_events_pinned_by_you" = "You pinned a message"; +"state_event_room_pinned_events_unpinned" = "%1$@ unpinned a message"; +"state_event_room_pinned_events_unpinned_by_you" = "You unpinned a message"; "state_event_room_reject" = "%1$@ menolak undangan"; "state_event_room_reject_by_you" = "Anda menolak undangan"; "state_event_room_remove" = "%1$@ mengeluarkan %2$@"; @@ -921,6 +988,7 @@ "screen_dm_details_unblock_user" = "Buka blokir pengguna"; "screen_edit_poll_delete_confirmation_title" = "Hapus pemungutan suara"; "screen_edit_poll_title" = "Sunting pemungutan suara"; +"screen_identity_use_another_device" = "Gunakan perangkat lain"; "screen_login_subtitle" = "Matrix adalah jaringan terbuka untuk komunikasi yang aman dan terdesentralisasi."; "screen_qr_code_login_invalid_scan_state_retry_button" = "Coba lagi"; "screen_report_content_block_user" = "Blokir pengguna"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "Keluar dari akun"; "screen_signout_confirmation_dialog_title" = "Keluar dari akun"; "screen_signout_preference_item" = "Keluar dari akun"; -"screen_waitlist_message_success" = "Selamat datang di %1$@!"; diff --git a/ElementX/Resources/Localizations/id.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/id.lproj/Localizable.stringsdict index b9e90183e2..b4e966a3b9 100644 --- a/ElementX/Resources/Localizations/id.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/id.lproj/Localizable.stringsdict @@ -170,6 +170,22 @@ PIN salah. Anda memiliki %1$d percobaan lagi + 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 diff --git a/ElementX/Resources/Localizations/it.lproj/Localizable.strings b/ElementX/Resources/Localizations/it.lproj/Localizable.strings index 0912b4a3e5..f3b48eb9dc 100644 --- a/ElementX/Resources/Localizations/it.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/it.lproj/Localizable.strings @@ -27,17 +27,20 @@ "action_back" = "Indietro"; "action_call" = "Chiama"; "action_cancel" = "Annulla"; +"action_cancel_for_now" = "Cancel for now"; "action_choose_photo" = "Scegli foto"; "action_clear" = "Cancella"; "action_close" = "Chiudi"; "action_complete_verification" = "Completa verifica"; "action_confirm" = "Conferma"; +"action_confirm_password" = "Confirm password"; "action_continue" = "Continua"; "action_copy" = "Copia"; "action_copy_link" = "Copia collegamento"; "action_copy_link_to_message" = "Copia collegamento al messaggio"; "action_create" = "Crea"; "action_create_a_room" = "Crea una stanza"; +"action_deactivate" = "Deactivate"; "action_decline" = "Rifiuta"; "action_delete_poll" = "Elimina sondaggio"; "action_disable" = "Disabilita"; @@ -70,6 +73,7 @@ "action_ok" = "OK"; "action_open_settings" = "Impostazioni"; "action_open_with" = "Apri con"; +"action_pin" = "Pin"; "action_quick_reply" = "Risposta rapida"; "action_quote" = "Citazione"; "action_react" = "Reagisci"; @@ -80,6 +84,7 @@ "action_report_bug" = "Segnala un problema"; "action_report_content" = "Segnala contenuto"; "action_reset" = "Reimposta"; +"action_reset_identity" = "Reimposta identitร "; "action_retry" = "Riprova"; "action_retry_decryption" = "Riprova la decrittazione"; "action_save" = "Salva"; @@ -99,10 +104,18 @@ "action_take_photo" = "Scatta foto"; "action_tap_for_options" = "Tocca per le opzioni"; "action_try_again" = "Riprova"; +"action_unpin" = "Rimuovi dai fissati"; +"action_view_in_timeline" = "View in timeline"; "action_view_source" = "Vedi codice sorgente"; "action_yes" = "Sรฌ"; "action.load_more" = "Carica altro"; -"action.pin" = "Pin"; +"action_deactivate_account" = "Deactivate account"; +"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" = "Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices."; +"banner.set_up_recovery.title" = "Set up recovery"; "common_about" = "Informazioni"; "common_acceptable_use_policy" = "Regole sull'utilizzo consentito"; "common_advanced_settings" = "Impostazioni avanzate"; @@ -213,7 +226,8 @@ "common_waiting" = "In attesaโ€ฆ"; "common_waiting_for_decryption_key" = "In attesa del messaggio"; "common.do_not_show_this_again" = "Non mostrarlo piรน"; -"common.open_source_licenses" = "Open source licenses"; +"common.open_source_licenses" = "Licenze open source"; +"common.pinned" = "Pinned"; "common.send_to" = "Invia a"; "common_no_room_name" = "Nessun nome della stanza"; "common_poll_end_confirmation" = "Vuoi davvero terminare questo sondaggio?"; @@ -244,6 +258,7 @@ "emoji_picker_category_people" = "Faccine & Persone"; "emoji_picker_category_places" = "Viaggi & Luoghi"; "emoji_picker_category_symbols" = "Simboli"; +"error_account_creation_not_possible" = "Your homeserver needs to be upgraded to support Matrix Authentication Service and account creation."; "error_failed_creating_the_permalink" = "Impossibile creare il collegamento permanente"; "error_failed_loading_map" = "%1$@ non รจ riuscito a caricare la mappa. Riprova piรน tardi."; "error_failed_loading_messages" = "Caricamento dei messaggi non riuscito"; @@ -253,10 +268,12 @@ "error_no_compatible_app_found" = "Non รจ stata trovata alcuna app compatibile per gestire questa azione."; "error_some_messages_have_not_been_sent" = "Alcuni messaggi non sono stati inviati"; "error_unknown" = "Siamo spiacenti, si รจ verificato un errore"; -"event_shield_reason_authenticity_not_guaranteed" = "The authenticity of this encrypted message can't be guaranteed on this device."; -"event_shield_reason_unknown_device" = "Encrypted by an unknown or deleted device."; -"event_shield_reason_unsigned_device" = "Encrypted by a device not verified by its owner."; -"event_shield_reason_unverified_identity" = "Encrypted by an unverified user."; +"event_shield_reason_authenticity_not_guaranteed" = "L'autenticitร  di questo messaggio cifrato non puรฒ essere garantita su questo dispositivo."; +"event_shield_reason_previously_verified" = "Encrypted by a previously-verified user."; +"event_shield_reason_sent_in_clear" = "Non cifrato."; +"event_shield_reason_unknown_device" = "Cifrato da un dispositivo sconosciuto o eliminato."; +"event_shield_reason_unsigned_device" = "Cifrato da un dispositivo non verificato dal proprietario."; +"event_shield_reason_unverified_identity" = "Cifrato da un utente non verificato."; "full_screen_intent_banner_message" = "Per non perdere mai una chiamata importante, modifica le impostazioni per consentire le notifiche a schermo intero quando il telefono รจ bloccato."; "full_screen_intent_banner_title" = "Migliora la tua esperienza di chiamata"; "invite_friends_rich_title" = "๐Ÿ”๏ธ Unisciti a me su %1$@"; @@ -275,11 +292,14 @@ "notification_inline_reply_failed" = "** Invio fallito - si prega di aprire la stanza"; "notification_invitation_action_reject" = "Rifiuta"; "notification_invite_body" = "Ti ha invitato ad una conversazione"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "notification_mentioned_you_body" = "Ti ha menzionato: %1$@"; "notification_new_messages" = "Nuovi messaggi"; "notification_reaction_body" = "Ha reagito con %1$@"; "notification_room_invite_body" = "Ti ha invitato ad entrare nella stanza"; +"notification_room_invite_body_with_sender" = "%1$@ invited you to join the room"; "notification_sender_me" = "Io"; +"notification_sender_mention_reply" = "%1$@ mentioned or replied"; "notification_test_push_notification_content" = "Stai visualizzando la notifica! Cliccami!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -312,10 +332,27 @@ "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_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_pinned_timeline_screen_title_empty" = "Messaggi fissati"; +"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" = "Notifica l'intera stanza"; -"screen.room.pinned_banner_indicator" = "%1$@ of %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ Pinned messages"; -"screen.room.pinned_banner_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_details_pinned_events_row_title" = "Messaggi fissati"; +"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_account_provider_change" = "Cambia fornitore dell'account"; "screen_account_provider_form_hint" = "Indirizzo dell'homeserver"; "screen_account_provider_form_notice" = "Inserisci un termine di ricerca o un indirizzo di dominio."; @@ -398,6 +435,7 @@ "screen_chat_backup_recovery_action_confirm_description" = "Il backup delle conversazioni non รจ attualmente sincronizzato."; "screen_chat_backup_recovery_action_setup" = "Configura il recupero"; "screen_chat_backup_recovery_action_setup_description" = "Ottieni l'accesso ai tuoi messaggi cifrati se perdi tutti i tuoi dispositivi o se sei disconnesso da %1$@ ovunque."; +"screen_create_account_title" = "Create account"; "screen_create_new_recovery_key_list_item_1" = "Apri %1$@ in un dispositivo desktop"; "screen_create_new_recovery_key_list_item_2" = "Accedi nuovamente al tuo account"; "screen_create_new_recovery_key_list_item_3" = "Quando ti viene chiesto di verificare il tuo dispositivo, seleziona %1$@"; @@ -421,6 +459,17 @@ "screen_create_room_public_option_description" = "I messaggi non sono cifrati e chiunque puรฒ leggerli. Puoi attivare la crittografia in un secondo momento."; "screen_create_room_public_option_title" = "Stanza pubblica (chiunque)"; "screen_create_room_topic_label" = "Argomento (facoltativo)"; +"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_edit_poll_delete_confirmation" = "Vuoi davvero eliminare questo sondaggio?"; "screen_edit_profile_display_name" = "Nome visualizzato"; "screen_edit_profile_display_name_placeholder" = "Il tuo nome visualizzato"; @@ -428,12 +477,20 @@ "screen_edit_profile_error_title" = "Impossibile aggiornare il profilo"; "screen_edit_profile_title" = "Modifica profilo"; "screen_edit_profile_updating_details" = "Aggiornamento del profiloโ€ฆ"; +"screen_encryption_reset_action_continue_reset" = "Continue reset"; +"screen_encryption_reset_bullet_1" = "I dettagli del tuo account, i contatti, le preferenze e l'elenco delle conversazioni verranno conservati"; +"screen_encryption_reset_bullet_2" = "Perderai la cronologia dei messaggi esistente"; +"screen_encryption_reset_bullet_3" = "Dovrai verificare nuovamente tutti i dispositivi e i contatti esistenti"; +"screen_encryption_reset_footer" = "Reimposta la tua identitร  solo se non hai accesso a un altro dispositivo su cui hai effettuato l'accesso e hai perso la chiave di recupero."; +"screen_encryption_reset_title" = "Reimposta la tua identitร  nel caso in cui non riesci a confermare in un altro modo"; +"screen_identity_confirmation_cannot_confirm" = "Non puoi confermare?"; "screen_identity_confirmation_create_new_recovery_key" = "Crea una nuova chiave di recupero"; "screen_identity_confirmation_subtitle" = "Verifica questo dispositivo per segnare i tuoi messaggi come sicuri."; "screen_identity_confirmation_title" = "Conferma la tua identitร "; +"screen_identity_confirmation_use_another_device" = "Usa un altro dispositivo"; +"screen_identity_confirmation_use_recovery_key" = "Usa la chiave di recupero"; "screen_identity_confirmed_subtitle" = "Ora puoi leggere o inviare messaggi in tutta sicurezza e anche chi chatta con te puรฒ fidarsi di questo dispositivo."; "screen_identity_confirmed_title" = "Dispositivo verificato"; -"screen_identity_use_another_device" = "Usa un altro dispositivo"; "screen_identity_waiting_on_other_device" = "In attesa sull'altro dispositivo..."; "screen_invites_decline_chat_message" = "Vuoi davvero rifiutare l'invito ad entrare in %1$@?"; "screen_invites_decline_chat_title" = "Rifiuta l'invito"; @@ -556,7 +613,6 @@ "screen_recovery_key_confirm_error_content" = "Riprova per confermare l'accesso al backup della chat."; "screen_recovery_key_confirm_error_title" = "Chiave di recupero errata"; "screen_recovery_key_confirm_key_description" = "Se hai una chiave di sicurezza o una password, andrร  bene anche questo."; -"screen_recovery_key_confirm_key_label" = "Chiave di recupero o codice di accesso"; "screen_recovery_key_confirm_key_placeholder" = "Inserisci..."; "screen_recovery_key_confirm_lost_recovery_key" = "Hai perso la chiave di recupero?"; "screen_recovery_key_confirm_success" = "Chiave di recupero confermata"; @@ -577,6 +633,14 @@ "screen_report_content_block_user_hint" = "Seleziona se vuoi nascondere tutti i messaggi attuali e futuri di questo utente"; "screen_report_content_explanation" = "Questo messaggio verrร  segnalato all'amministratore dell'homeserver. Questi non sarร  in grado di leggere i messaggi cifrati."; "screen_report_content_hint" = "Motivo della segnalazione di questo contenuto"; +"screen_reset_encryption_confirmation_alert_action" = "Sรฌ, reimposta ora"; +"screen_reset_encryption_confirmation_alert_subtitle" = "Questo processo รจ irreversibile."; +"screen_reset_encryption_confirmation_alert_title" = "Sei sicuro di voler reimpostare la crittografia?"; +"screen_reset_encryption_password_placeholder" = "Inserisciโ€ฆ"; +"screen_reset_encryption_password_subtitle" = "Conferma di voler reimpostare la crittografia."; +"screen_reset_encryption_password_title" = "Inserisci la password del tuo account per continuare"; +"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_room_alias_resolver_resolve_alias_failure" = "Impossibile risolvere l'alias della stanza."; "screen_room_attachment_source_camera" = "Fotocamera"; "screen_room_attachment_source_camera_video" = "Registra video"; @@ -775,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "Hai salvato la chiave di recupero?"; "screen_start_chat_error_starting_chat" = "Si รจ verificato un errore durante il tentativo di avviare una chat"; "screen_view_location_title" = "Posizione"; -"screen_waitlist_message" = "Al momento c'รจ una grande richiesta per %1$@ su %2$@. Torna a visitare l'app tra qualche giorno e riprova.\n\nGrazie per la pazienza!"; -"screen_waitlist_title" = "Ci sei quasi."; -"screen_waitlist_title_success" = "Sei dentro."; "screen_welcome_bullet_1" = "Chiamate, sondaggi, ricerche e altro ancora saranno aggiunti nel corso dell'anno."; "screen_welcome_bullet_2" = "La cronologia dei messaggi per le stanze crittografate non รจ ancora disponibile."; "screen_welcome_bullet_3" = "Ci piacerebbe sentire il tuo parere, facci sapere cosa ne pensi tramite la pagina delle impostazioni."; @@ -834,6 +895,12 @@ "state_event_room_name_removed_by_you" = "Hai rimosso il nome della stanza"; "state_event_room_none" = "%1$@ non ha apportato modifiche"; "state_event_room_none_by_you" = "Non hai apportato modifiche"; +"state_event_room_pinned_events_changed" = "%1$@ ha modificato i messaggi fissati"; +"state_event_room_pinned_events_changed_by_you" = "Hai modificato i messaggi fissati"; +"state_event_room_pinned_events_pinned" = "%1$@ ha fissato un messaggio"; +"state_event_room_pinned_events_pinned_by_you" = "Hai fissato un messaggio"; +"state_event_room_pinned_events_unpinned" = "%1$@ ha rimosso un messaggio dai fissati"; +"state_event_room_pinned_events_unpinned_by_you" = "Hai rimosso un messaggio dai fissati"; "state_event_room_reject" = "%1$@ ha rifiutato l'invito"; "state_event_room_reject_by_you" = "Hai rifiutato l'invito"; "state_event_room_remove" = "%1$@ ha rimosso %2$@"; @@ -921,6 +988,7 @@ "screen_dm_details_unblock_user" = "Sblocca utente"; "screen_edit_poll_delete_confirmation_title" = "Elimina sondaggio"; "screen_edit_poll_title" = "Modifica sondaggio"; +"screen_identity_use_another_device" = "Usa un altro dispositivo"; "screen_login_subtitle" = "Matrix รจ una rete aperta per comunicazioni sicure e decentralizzate."; "screen_qr_code_login_invalid_scan_state_retry_button" = "Riprova"; "screen_report_content_block_user" = "Blocca utente"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "Disconnetti"; "screen_signout_confirmation_dialog_title" = "Disconnetti"; "screen_signout_preference_item" = "Disconnetti"; -"screen_waitlist_message_success" = "Benvenuti in %1$@!"; diff --git a/ElementX/Resources/Localizations/it.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/it.lproj/Localizable.stringsdict index e8e4aa8e92..f144b6b3be 100644 --- a/ElementX/Resources/Localizations/it.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/it.lproj/Localizable.stringsdict @@ -194,6 +194,22 @@ PIN sbagliato. Hai altri %1$d tentativi + screen_pinned_timeline_screen_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d Messaggio fissato + other + %1$d Messaggi fissati + + screen_room_member_list_header_title NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/ka.lproj/Localizable.strings b/ElementX/Resources/Localizations/ka.lproj/Localizable.strings index 45514726ed..c8c3acb277 100644 --- a/ElementX/Resources/Localizations/ka.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/ka.lproj/Localizable.strings @@ -27,17 +27,20 @@ "action_back" = "แƒฃแƒ™แƒแƒœ"; "action_call" = "Call"; "action_cancel" = "แƒ’แƒแƒฃแƒฅแƒ›แƒ”แƒ‘แƒ"; +"action_cancel_for_now" = "Cancel for now"; "action_choose_photo" = "แƒแƒ˜แƒ แƒฉแƒ˜แƒ”แƒ— แƒคแƒแƒขแƒ"; "action_clear" = "แƒ’แƒแƒกแƒฃแƒคแƒ—แƒแƒ•แƒ”แƒ‘แƒ"; "action_close" = "แƒ“แƒแƒฎแƒฃแƒ แƒ•แƒ"; "action_complete_verification" = "แƒ“แƒแƒ“แƒแƒกแƒขแƒฃแƒ แƒ”แƒ‘แƒ˜แƒก แƒ“แƒแƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ"; "action_confirm" = "แƒ“แƒแƒ“แƒแƒกแƒขแƒฃแƒ แƒ”แƒ‘แƒ"; +"action_confirm_password" = "Confirm password"; "action_continue" = "แƒ’แƒแƒ’แƒ แƒซแƒ”แƒšแƒ”แƒ‘แƒ"; "action_copy" = "แƒ™แƒแƒžแƒ˜แƒ แƒ”แƒ‘แƒ"; "action_copy_link" = "แƒ‘แƒ›แƒฃแƒšแƒ˜แƒก แƒ™แƒแƒžแƒ˜แƒ แƒ”แƒ‘แƒ"; "action_copy_link_to_message" = "แƒ“แƒแƒแƒ™แƒแƒžแƒ˜แƒ แƒ”แƒ— แƒจแƒ”แƒขแƒงแƒแƒ‘แƒ˜แƒœแƒ”แƒ‘แƒ˜แƒก แƒ‘แƒ›แƒฃแƒšแƒ˜"; "action_create" = "แƒจแƒ”แƒฅแƒ›แƒœแƒ"; "action_create_a_room" = "แƒแƒ—แƒแƒฎแƒ˜แƒก แƒจแƒ”แƒฅแƒ›แƒœแƒ"; +"action_deactivate" = "Deactivate"; "action_decline" = "แƒฃแƒแƒ แƒงแƒแƒคแƒ"; "action_delete_poll" = "แƒ’แƒแƒ›แƒแƒ™แƒ˜แƒ—แƒฎแƒ•แƒ˜แƒก แƒฌแƒแƒจแƒšแƒ"; "action_disable" = "แƒ’แƒแƒ›แƒแƒ แƒ—แƒ•แƒ"; @@ -70,6 +73,7 @@ "action_ok" = "OK"; "action_open_settings" = "แƒžแƒแƒ แƒแƒ›แƒ”แƒขแƒ แƒ”แƒ‘แƒ˜"; "action_open_with" = "แƒ’แƒแƒฎแƒกแƒœแƒ แƒžแƒ แƒแƒ’แƒ แƒแƒ›แƒ˜แƒ—:"; +"action_pin" = "Pin"; "action_quick_reply" = "แฒกแƒฌแƒ แƒแƒคแƒ˜ แƒžแƒแƒกแƒฃแƒฎแƒ˜"; "action_quote" = "แƒชแƒ˜แƒขแƒ˜แƒ แƒ”แƒ‘แƒ"; "action_react" = "แƒ แƒ”แƒแƒ’แƒ˜แƒ แƒ”แƒ‘แƒ"; @@ -80,6 +84,7 @@ "action_report_bug" = "แƒฎแƒแƒ แƒ•แƒ”แƒ–แƒ˜แƒก แƒจแƒ”แƒขแƒงแƒแƒ‘แƒ˜แƒœแƒ”แƒ‘แƒ"; "action_report_content" = "แƒ™แƒแƒœแƒขแƒ”แƒœแƒขแƒ˜แƒก แƒ แƒ”แƒžแƒแƒ แƒขแƒ˜"; "action_reset" = "Reset"; +"action_reset_identity" = "Reset identity"; "action_retry" = "แƒฎแƒ”แƒšแƒแƒฎแƒšแƒ แƒชแƒ“แƒ"; "action_retry_decryption" = "แƒ’แƒแƒจแƒ˜แƒคแƒ•แƒ แƒ˜แƒก แƒฎแƒ”แƒšแƒแƒฎแƒšแƒ แƒชแƒ“แƒ"; "action_save" = "แƒจแƒ”แƒœแƒแƒฎแƒ•แƒ"; @@ -99,10 +104,18 @@ "action_take_photo" = "แƒคแƒแƒขแƒแƒก แƒ’แƒแƒ“แƒแƒฆแƒ”แƒ‘แƒ"; "action_tap_for_options" = "แƒจแƒ”แƒ”แƒฎแƒ”แƒ— แƒ•แƒแƒ แƒ˜แƒแƒœแƒขแƒ”แƒ‘แƒ˜แƒก แƒกแƒแƒœแƒแƒฎแƒแƒ•แƒแƒ“"; "action_try_again" = "แƒฎแƒ”แƒšแƒแƒฎแƒšแƒ แƒชแƒ“แƒ"; +"action_unpin" = "Unpin"; +"action_view_in_timeline" = "View in timeline"; "action_view_source" = "แƒฌแƒงแƒแƒ แƒแƒก แƒœแƒแƒฎแƒ•แƒ"; "action_yes" = "แƒ“แƒ˜แƒแƒฎ"; "action.load_more" = "แƒ›แƒ”แƒขแƒ˜แƒก แƒฉแƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒ"; -"action.pin" = "Pin"; +"action_deactivate_account" = "Deactivate account"; +"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" = "Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices."; +"banner.set_up_recovery.title" = "Set up recovery"; "common_about" = "แƒจแƒ”แƒกแƒแƒฎแƒ”แƒ‘"; "common_acceptable_use_policy" = "แƒ›แƒ˜แƒกแƒแƒฆแƒ”แƒ‘แƒ˜ แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒ˜แƒก แƒžแƒแƒšแƒ˜แƒขแƒ˜แƒ™แƒ"; "common_advanced_settings" = "แƒ’แƒแƒคแƒแƒ แƒ—แƒแƒ”แƒ‘แƒฃแƒšแƒ˜ แƒžแƒแƒ แƒแƒ›แƒ”แƒขแƒ แƒ”แƒ‘แƒ˜"; @@ -214,6 +227,7 @@ "common_waiting_for_decryption_key" = "แƒšแƒแƒ“แƒ˜แƒœแƒ˜ แƒแƒ› แƒจแƒ”แƒขแƒงแƒแƒ‘แƒ˜แƒœแƒ”แƒ‘แƒ˜แƒกแƒแƒ—แƒ•แƒ˜แƒก"; "common.do_not_show_this_again" = "Do not show this again"; "common.open_source_licenses" = "Open source licenses"; +"common.pinned" = "Pinned"; "common.send_to" = "Send to"; "common_no_room_name" = "No room name"; "common_poll_end_confirmation" = "แƒ“แƒแƒ แƒฌแƒ›แƒฃแƒœแƒ”แƒ‘แƒฃแƒšแƒ˜ แƒฎแƒแƒ แƒ—, แƒ แƒแƒ› แƒ’แƒกแƒฃแƒ แƒ— แƒแƒ› แƒ’แƒแƒ›แƒแƒ™แƒ˜แƒ—แƒฎแƒ•แƒ˜แƒก แƒ“แƒแƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ?"; @@ -244,6 +258,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_failed_creating_the_permalink" = "แƒ›แƒฃแƒ“แƒ›แƒ˜แƒ•แƒ˜ แƒ‘แƒ›แƒฃแƒšแƒ˜แƒก แƒจแƒ”แƒฅแƒ›แƒœแƒ แƒ•แƒ”แƒ  แƒ›แƒแƒฎแƒ”แƒ แƒฎแƒ“แƒ"; "error_failed_loading_map" = "แƒ•แƒ”แƒ  แƒ’แƒแƒ›แƒแƒ•แƒ˜แƒ“แƒ แƒ แƒฃแƒ™แƒ˜แƒก %1$@ แƒฉแƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒ. แƒ’แƒ—แƒฎแƒแƒ•แƒ—, แƒ›แƒแƒ’แƒ•แƒ˜แƒแƒœแƒ”แƒ‘แƒ˜แƒ— แƒกแƒชแƒแƒ“แƒแƒ—."; "error_failed_loading_messages" = "แƒจแƒ”แƒขแƒงแƒแƒ‘แƒ˜แƒœแƒ”แƒ‘แƒ”แƒ‘แƒ˜แƒก แƒฉแƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒ แƒ•แƒ”แƒ  แƒ›แƒแƒฎแƒ”แƒ แƒฎแƒ“แƒ"; @@ -254,6 +269,8 @@ "error_some_messages_have_not_been_sent" = "แƒ–แƒแƒ’แƒ˜แƒ”แƒ แƒ—แƒ˜ แƒจแƒ”แƒขแƒงแƒแƒ‘แƒ˜แƒœแƒ”แƒ‘แƒ แƒแƒ  แƒ’แƒแƒ˜แƒ’แƒ–แƒแƒ•แƒœแƒ"; "error_unknown" = "แƒ‘แƒแƒ“แƒ˜แƒจแƒ˜แƒ—, แƒจแƒ”แƒชแƒ“แƒแƒ›แƒ แƒ›แƒแƒฎแƒ“แƒ"; "event_shield_reason_authenticity_not_guaranteed" = "The authenticity of this encrypted message can't be guaranteed on this device."; +"event_shield_reason_previously_verified" = "Encrypted by a previously-verified user."; +"event_shield_reason_sent_in_clear" = "Not encrypted."; "event_shield_reason_unknown_device" = "Encrypted by an unknown or deleted device."; "event_shield_reason_unsigned_device" = "Encrypted by a device not verified by its owner."; "event_shield_reason_unverified_identity" = "Encrypted by an unverified user."; @@ -275,11 +292,14 @@ "notification_inline_reply_failed" = "** แƒ’แƒแƒ’แƒ–แƒแƒ•แƒœแƒ แƒ•แƒ”แƒ  แƒ›แƒแƒฎแƒ”แƒ แƒฎแƒ“แƒ - แƒ’แƒ—แƒฎแƒแƒ•แƒ—, แƒ’แƒแƒฎแƒกแƒœแƒแƒ— แƒแƒ—แƒแƒฎแƒ˜"; "notification_invitation_action_reject" = "แƒฃแƒแƒ แƒงแƒแƒคแƒ"; "notification_invite_body" = "แƒ›แƒแƒ’แƒ˜แƒฌแƒ•แƒ˜แƒแƒ— แƒฉแƒแƒขแƒจแƒ˜"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "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_sender_me" = "แƒ›แƒ”"; +"notification_sender_mention_reply" = "%1$@ mentioned or replied"; "notification_test_push_notification_content" = "แƒ—แƒฅแƒ•แƒ”แƒœ แƒฎแƒ”แƒ“แƒแƒ•แƒ— แƒจแƒ”แƒขแƒงแƒแƒ‘แƒ˜แƒœแƒ”แƒ‘แƒแƒก! แƒ“แƒแƒ›แƒแƒฌแƒ™แƒแƒžแƒฃแƒœแƒ”แƒ—!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -312,10 +332,27 @@ "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_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_pinned_timeline_screen_title_empty" = "Pinned messages"; +"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.room.pinned_banner_indicator" = "%1$@ of %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ Pinned messages"; -"screen.room.pinned_banner_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_details_pinned_events_row_title" = "Pinned messages"; +"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_account_provider_change" = "แƒแƒœแƒ’แƒแƒ แƒ˜แƒจแƒ˜แƒก แƒ›แƒ˜แƒ›แƒฌแƒแƒ“แƒ”แƒ‘แƒšแƒ˜แƒก แƒจแƒ”แƒชแƒ•แƒšแƒ"; "screen_account_provider_form_hint" = "แƒกแƒแƒฎแƒšแƒ˜แƒก แƒกแƒ”แƒ แƒ•แƒ”แƒ แƒ˜แƒก แƒ›แƒ˜แƒกแƒแƒ›แƒแƒ แƒ—แƒ˜"; "screen_account_provider_form_notice" = "แƒจแƒ”แƒ˜แƒงแƒ•แƒแƒœแƒ”แƒ— แƒกแƒแƒซแƒ˜แƒ”แƒ‘แƒ แƒกแƒ˜แƒขแƒงแƒ•แƒ แƒแƒœ แƒ“แƒแƒ›แƒ”แƒœแƒ˜แƒก แƒ›แƒ˜แƒกแƒแƒ›แƒแƒ แƒ—แƒ˜."; @@ -398,6 +435,7 @@ "screen_chat_backup_recovery_action_confirm_description" = "แƒ—แƒฅแƒ•แƒ”แƒœแƒ˜ แƒฉแƒแƒขแƒ˜แƒก แƒกแƒแƒ แƒ”แƒ–แƒ”แƒ แƒ•แƒ แƒแƒกแƒšแƒ˜ แƒแƒ›แƒŸแƒแƒ›แƒแƒ“ แƒแƒ  แƒแƒ แƒ˜แƒก แƒกแƒ˜แƒœแƒฅแƒ แƒแƒœแƒ˜แƒ–แƒ”แƒ‘แƒฃแƒšแƒ˜."; "screen_chat_backup_recovery_action_setup" = "แƒแƒฆแƒ“แƒ’แƒ”แƒœแƒ˜แƒก แƒ“แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒ"; "screen_chat_backup_recovery_action_setup_description" = "แƒ›แƒ˜แƒ˜แƒฆแƒ”แƒ— แƒฌแƒ•แƒ“แƒแƒ›แƒ แƒ—แƒฅแƒ•แƒ”แƒœแƒก แƒ“แƒแƒจแƒ˜แƒคแƒ แƒฃแƒš แƒจแƒ”แƒขแƒงแƒแƒ‘แƒ˜แƒœแƒ”แƒ‘แƒ”แƒ‘แƒ–แƒ”, แƒ—แƒฃ แƒ“แƒแƒ™แƒแƒ แƒ’แƒแƒ•แƒ— แƒ—แƒฅแƒ•แƒ”แƒœแƒก แƒงแƒ•แƒ”แƒšแƒ แƒ›แƒแƒฌแƒงแƒแƒ‘แƒ˜แƒšแƒแƒ‘แƒแƒก แƒแƒœ แƒ’แƒแƒ›แƒแƒฎแƒ•แƒแƒšแƒ— แƒกแƒ˜แƒกแƒขแƒ”แƒ›แƒ˜แƒ“แƒแƒœ %1$@-แƒ“แƒแƒœ แƒงแƒ•แƒ”แƒšแƒ’แƒแƒœ."; +"screen_create_account_title" = "Create account"; "screen_create_new_recovery_key_list_item_1" = "Open %1$@ in a desktop device"; "screen_create_new_recovery_key_list_item_2" = "Sign into your account again"; "screen_create_new_recovery_key_list_item_3" = "When asked to verify your device, select %1$@"; @@ -421,6 +459,17 @@ "screen_create_room_public_option_description" = "แƒจแƒ”แƒขแƒงแƒแƒ‘แƒ˜แƒœแƒ”แƒ‘แƒ”แƒ‘แƒ˜ แƒแƒ  แƒแƒ แƒ˜แƒก แƒ“แƒแƒจแƒ˜แƒคแƒ แƒฃแƒšแƒ˜ แƒ“แƒ แƒงแƒ•แƒ”แƒšแƒแƒก แƒจแƒ”แƒฃแƒซแƒšแƒ˜แƒ แƒ›แƒแƒ—แƒ˜ แƒฌแƒแƒ™แƒ˜แƒ—แƒฎแƒ•แƒ. แƒจแƒ”แƒ’แƒ˜แƒซแƒšแƒ˜แƒแƒ— แƒฉแƒแƒ แƒ—แƒแƒ— แƒ“แƒแƒจแƒ˜แƒคแƒ•แƒ แƒ แƒ›แƒแƒ’แƒ•แƒ˜แƒแƒœแƒ”แƒ‘แƒ˜แƒ—."; "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_edit_poll_delete_confirmation" = "แƒ“แƒแƒ แƒฌแƒ›แƒฃแƒœแƒ”แƒ‘แƒฃแƒšแƒ˜ แƒฎแƒแƒ แƒ—, แƒ แƒแƒ› แƒ’แƒกแƒฃแƒ แƒ— แƒแƒ› แƒ’แƒแƒ›แƒแƒ™แƒ˜แƒ—แƒฎแƒ•แƒ˜แƒก แƒฌแƒแƒจแƒšแƒ?"; "screen_edit_profile_display_name" = "แƒœแƒแƒฉแƒ•แƒ”แƒœแƒ”แƒ‘แƒ˜ แƒกแƒแƒฎแƒ”แƒšแƒ˜"; "screen_edit_profile_display_name_placeholder" = "แƒ—แƒฅแƒ•แƒ”แƒœแƒ˜ แƒœแƒแƒฉแƒ•แƒ”แƒœแƒ”แƒ‘แƒ˜ แƒกแƒแƒฎแƒ”แƒšแƒ˜"; @@ -428,12 +477,20 @@ "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" = "Your account details, contacts, preferences, and chat list will be kept"; +"screen_encryption_reset_bullet_2" = "You will lose your existing message history"; +"screen_encryption_reset_bullet_3" = "You will need to verify all your existing devices and contacts again"; +"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_identity_confirmation_create_new_recovery_key" = "Create a new recovery key"; "screen_identity_confirmation_subtitle" = "Verify this device to set up secure messaging."; -"screen_identity_confirmation_title" = "Confirm that it's you"; +"screen_identity_confirmation_title" = "Confirm your identity"; +"screen_identity_confirmation_use_another_device" = "Use another device"; +"screen_identity_confirmation_use_recovery_key" = "Use recovery key"; "screen_identity_confirmed_subtitle" = "Now you can read or send messages securely, and anyone you chat with can also trust this device."; "screen_identity_confirmed_title" = "Device verified"; -"screen_identity_use_another_device" = "Use another device"; "screen_identity_waiting_on_other_device" = "Waiting on other deviceโ€ฆ"; "screen_invites_decline_chat_message" = "แƒ“แƒแƒ แƒฌแƒ›แƒฃแƒœแƒ”แƒ‘แƒฃแƒšแƒ˜ แƒฎแƒแƒ แƒ—, แƒ แƒแƒ› แƒ’แƒกแƒฃแƒ แƒ—, แƒฃแƒแƒ แƒ˜ แƒ—แƒฅแƒ•แƒแƒ— แƒ›แƒแƒฌแƒ•แƒ”แƒ•แƒแƒ–แƒ” %1$@-แƒจแƒ˜?"; "screen_invites_decline_chat_title" = "แƒ›แƒแƒฌแƒ•แƒ”แƒ•แƒแƒ–แƒ” แƒฃแƒแƒ แƒ˜แƒก แƒ—แƒฅแƒ›แƒ"; @@ -556,7 +613,6 @@ "screen_recovery_key_confirm_error_content" = "แƒ’แƒ—แƒฎแƒแƒ•แƒ—, แƒกแƒชแƒแƒ“แƒแƒ— แƒฎแƒ”แƒšแƒแƒฎแƒšแƒ, แƒ แƒแƒ—แƒ แƒ—แƒฅแƒ•แƒ”แƒœแƒ˜ แƒฉแƒ”แƒ—แƒ˜แƒก แƒกแƒแƒ แƒ”แƒ–แƒ”แƒ แƒ•แƒ แƒแƒกแƒšแƒแƒ–แƒ” แƒฌแƒ•แƒ“แƒแƒ›แƒ แƒ“แƒแƒแƒ“แƒแƒกแƒขแƒฃแƒ แƒแƒ—"; "screen_recovery_key_confirm_error_title" = "แƒแƒฆแƒ“แƒ’แƒ”แƒœแƒ˜แƒก แƒแƒ แƒแƒกแƒฌแƒแƒ แƒ˜ แƒ’แƒแƒกแƒแƒฆแƒ”แƒ‘แƒ˜"; "screen_recovery_key_confirm_key_description" = "แƒ—แƒฃ แƒ—แƒฅแƒ•แƒ”แƒœ แƒ’แƒแƒฅแƒ•แƒ— แƒฃแƒกแƒแƒคแƒ แƒ—แƒฎแƒแƒ”แƒ‘แƒ˜แƒก แƒ’แƒแƒกแƒแƒฆแƒ”แƒ‘แƒ˜ แƒแƒœ แƒฃแƒกแƒแƒคแƒ แƒ—แƒฎแƒแƒ”แƒ‘แƒ˜แƒก แƒคแƒ แƒแƒ–แƒ, แƒ”แƒก แƒแƒกแƒ”แƒ•แƒ” แƒ˜แƒ›แƒฃแƒจแƒแƒ•แƒ”แƒ‘แƒก."; -"screen_recovery_key_confirm_key_label" = "Recovery key or passcode"; "screen_recovery_key_confirm_key_placeholder" = "แƒจแƒ”แƒงแƒ•แƒแƒœแƒ"; "screen_recovery_key_confirm_lost_recovery_key" = "Lost your recovery key?"; "screen_recovery_key_confirm_success" = "แƒแƒฆแƒ“แƒ’แƒ”แƒœแƒ˜แƒก แƒ’แƒแƒกแƒแƒฆแƒ”แƒ‘แƒ˜ แƒ“แƒแƒ“แƒแƒกแƒขแƒฃแƒ แƒ”แƒ‘แƒฃแƒšแƒ˜แƒ"; @@ -577,6 +633,14 @@ "screen_report_content_block_user_hint" = "แƒจแƒ”แƒแƒ›แƒแƒฌแƒ›แƒ”แƒ—, แƒ’แƒกแƒฃแƒ แƒ— แƒ—แƒฃ แƒแƒ แƒ แƒแƒ› แƒ›แƒแƒ›แƒฎแƒ›แƒแƒ แƒ”แƒ‘แƒšแƒ˜แƒก แƒงแƒ•แƒ”แƒšแƒ แƒ›แƒ˜แƒ›แƒ“แƒ˜แƒœแƒแƒ แƒ” แƒ“แƒ แƒ›แƒแƒ›แƒแƒ•แƒแƒšแƒ˜ แƒจแƒ”แƒขแƒงแƒแƒ‘แƒ˜แƒœแƒ”แƒ‘แƒ˜แƒก แƒ“แƒแƒ›แƒแƒšแƒ•แƒ"; "screen_report_content_explanation" = "แƒ”แƒก แƒจแƒ”แƒขแƒงแƒแƒ‘แƒ˜แƒœแƒ”แƒ‘แƒ แƒ’แƒแƒ’แƒ–แƒแƒ•แƒœแƒ˜แƒšแƒ˜ แƒ˜แƒฅแƒœแƒ”แƒ‘แƒ แƒ—แƒฅแƒ•แƒ”แƒœแƒ˜ แƒกแƒแƒฎแƒšแƒ˜แƒก แƒกแƒ”แƒ แƒ•แƒ”แƒ แƒ˜แƒก แƒแƒ“แƒ›แƒ˜แƒœแƒ˜แƒกแƒขแƒ แƒแƒขแƒแƒ แƒ˜แƒกแƒแƒ“แƒ›แƒ˜. แƒ›แƒแƒก แƒแƒ  แƒ”แƒฅแƒœแƒ”แƒ‘แƒ แƒ“แƒแƒจแƒ˜แƒคแƒ•แƒ แƒฃแƒšแƒ˜ แƒจแƒ”แƒขแƒงแƒแƒ‘แƒ˜แƒœแƒ”แƒ‘แƒ”แƒ‘แƒ˜แƒก แƒฌแƒแƒ™แƒ˜แƒ—แƒฎแƒ•แƒ˜แƒก แƒจแƒ”แƒกแƒแƒซแƒšแƒ”แƒ‘แƒšแƒแƒ‘แƒ."; "screen_report_content_hint" = "แƒแƒ› แƒ™แƒแƒœแƒขแƒ”แƒœแƒขแƒ˜แƒก แƒ“แƒแƒ แƒ”แƒžแƒแƒ แƒขแƒ”แƒ‘แƒ˜แƒก แƒ›แƒ˜แƒ–แƒ”แƒ–แƒ˜"; +"screen_reset_encryption_confirmation_alert_action" = "Yes, reset now"; +"screen_reset_encryption_confirmation_alert_subtitle" = "This process is irreversible."; +"screen_reset_encryption_confirmation_alert_title" = "Are you sure you want to reset your identity?"; +"screen_reset_encryption_password_placeholder" = "Enterโ€ฆ"; +"screen_reset_encryption_password_subtitle" = "Confirm that you want to reset your identity."; +"screen_reset_encryption_password_title" = "Enter your account password to continue"; +"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_room_alias_resolver_resolve_alias_failure" = "Failed to resolve room alias."; "screen_room_attachment_source_camera" = "แƒ™แƒแƒ›แƒ”แƒ แƒ"; "screen_room_attachment_source_camera_video" = "แƒ•แƒ˜แƒ“แƒ”แƒแƒก แƒฉแƒแƒฌแƒ”แƒ แƒ"; @@ -775,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "แƒจแƒ”แƒ˜แƒœแƒแƒฎแƒ”แƒ— แƒ—แƒฅแƒ•แƒ”แƒœแƒ˜ แƒแƒฆแƒ“แƒ’แƒ”แƒœแƒ˜แƒก แƒ’แƒแƒกแƒแƒฆแƒ”แƒ‘แƒ˜?"; "screen_start_chat_error_starting_chat" = "แƒฉแƒแƒขแƒ˜แƒก แƒ“แƒแƒฌแƒงแƒ”แƒ‘แƒ˜แƒก แƒ›แƒชแƒ“แƒ”แƒšแƒแƒ‘แƒ˜แƒกแƒแƒก แƒจแƒ”แƒชแƒ“แƒแƒ›แƒ แƒ›แƒแƒฎแƒ“แƒ"; "screen_view_location_title" = "แƒแƒ“แƒ’แƒ˜แƒšแƒ›แƒ“แƒ”แƒ‘แƒแƒ แƒ”แƒแƒ‘แƒ"; -"screen_waitlist_message" = "แƒแƒฎแƒšแƒ แƒ“แƒ˜แƒ“แƒ˜ แƒ›แƒแƒ—แƒฎแƒแƒ•แƒœแƒแƒ %1$@-แƒ–แƒ” %2$@-แƒจแƒ˜. แƒ“แƒแƒ‘แƒ แƒฃแƒœแƒ“แƒ˜แƒ— แƒ แƒแƒ›แƒ“แƒ”แƒœแƒ˜แƒ›แƒ” แƒ“แƒฆแƒ”แƒจแƒ˜ แƒ“แƒ แƒกแƒชแƒแƒ“แƒ”แƒ— แƒ”แƒ แƒ—แƒฎแƒ”แƒšแƒแƒช.\n\nแƒ›แƒแƒ“แƒšแƒแƒ‘แƒ แƒ›แƒแƒ—แƒ›แƒ”แƒœแƒ˜แƒกแƒแƒ—แƒ•แƒ˜แƒก!"; -"screen_waitlist_title" = "แƒ—แƒ˜แƒ—แƒฅแƒ›แƒ˜แƒก แƒ›แƒ–แƒแƒ“แƒแƒ."; -"screen_waitlist_title_success" = "แƒ—แƒฅแƒ•แƒ”แƒœ แƒจแƒ”แƒฎแƒ•แƒ”แƒ“แƒ˜แƒ—."; "screen_welcome_bullet_1" = "แƒ–แƒแƒ แƒ”แƒ‘แƒ˜, แƒ’แƒแƒ›แƒแƒ™แƒ˜แƒ—แƒฎแƒ•แƒ”แƒ‘แƒ˜, แƒซแƒ˜แƒ”แƒ‘แƒ แƒ“แƒ แƒกแƒฎแƒ•แƒ แƒ“แƒแƒ”แƒ›แƒแƒขแƒ”แƒ‘แƒ แƒแƒ› แƒฌแƒšแƒ˜แƒก แƒ‘แƒแƒšแƒแƒก."; "screen_welcome_bullet_2" = "แƒ“แƒแƒจแƒ˜แƒคแƒ แƒฃแƒšแƒ˜ แƒแƒ—แƒแƒฎแƒ”แƒ‘แƒ˜แƒกแƒ—แƒ•แƒ˜แƒก แƒจแƒ”แƒขแƒงแƒแƒ‘แƒ˜แƒœแƒ”แƒ‘แƒ”แƒ‘แƒ˜แƒก แƒ˜แƒกแƒขแƒแƒ แƒ˜แƒ แƒฏแƒ”แƒ  แƒแƒ  แƒแƒ แƒ˜แƒก แƒฎแƒ”แƒšแƒ›แƒ˜แƒกแƒแƒฌแƒ•แƒ“แƒแƒ›แƒ˜."; "screen_welcome_bullet_3" = "แƒฉแƒ•แƒ”แƒœ แƒกแƒ˜แƒแƒ›แƒแƒ•แƒœแƒ”แƒ‘แƒ˜แƒ— แƒ›แƒแƒ•แƒ˜แƒกแƒ›แƒ˜แƒœแƒแƒ— แƒ—แƒฅแƒ•แƒ”แƒœแƒ’แƒแƒœ, แƒจแƒ”แƒ’แƒ•แƒแƒขแƒงแƒแƒ‘แƒ˜แƒœแƒ”แƒ— แƒ แƒแƒก แƒคแƒ˜แƒฅแƒ แƒแƒ‘แƒ— แƒžแƒแƒ แƒแƒ›แƒ”แƒขแƒ แƒ”แƒ‘แƒ˜แƒก แƒ’แƒ•แƒ”แƒ แƒ“แƒ–แƒ”."; @@ -834,6 +895,12 @@ "state_event_room_name_removed_by_you" = "แƒ—แƒฅแƒ•แƒ”แƒœ แƒฌแƒแƒจแƒแƒšแƒ”แƒ— แƒแƒ—แƒแƒฎแƒ˜แƒก แƒกแƒแƒฎแƒ”แƒšแƒ˜"; "state_event_room_none" = "%1$@ made no changes"; "state_event_room_none_by_you" = "You made no changes"; +"state_event_room_pinned_events_changed" = "%1$@ changed the pinned messages"; +"state_event_room_pinned_events_changed_by_you" = "You changed the pinned messages"; +"state_event_room_pinned_events_pinned" = "%1$@ pinned a message"; +"state_event_room_pinned_events_pinned_by_you" = "You pinned a message"; +"state_event_room_pinned_events_unpinned" = "%1$@ unpinned a message"; +"state_event_room_pinned_events_unpinned_by_you" = "You unpinned a message"; "state_event_room_reject" = "%1$@ แƒ›แƒแƒฌแƒ•แƒ”แƒ•แƒแƒ–แƒ” แƒฃแƒแƒ แƒ˜ แƒ—แƒฅแƒ•แƒ"; "state_event_room_reject_by_you" = "แƒ—แƒฅแƒ•แƒ”แƒœ แƒฃแƒแƒ แƒ˜ แƒ—แƒฅแƒ•แƒ˜แƒ— แƒ›แƒแƒฌแƒ•แƒ”แƒ•แƒแƒ–แƒ”"; "state_event_room_remove" = "%1$@ แƒ’แƒแƒแƒ’แƒ“แƒ %2$@"; @@ -921,6 +988,7 @@ "screen_dm_details_unblock_user" = "แฒ›แƒแƒ›แƒฎแƒ›แƒแƒ แƒ”แƒ‘แƒšแƒ˜แƒก แƒ’แƒแƒœแƒ‘แƒšแƒแƒ™แƒ•แƒ"; "screen_edit_poll_delete_confirmation_title" = "แƒ’แƒแƒ›แƒแƒ™แƒ˜แƒ—แƒฎแƒ•แƒ˜แƒก แƒฌแƒแƒจแƒšแƒ"; "screen_edit_poll_title" = "แƒ’แƒแƒ›แƒแƒ™แƒ˜แƒ—แƒฎแƒ•แƒ˜แƒก แƒ แƒ”แƒ“แƒแƒฅแƒขแƒ˜แƒ แƒ”แƒ‘แƒ"; +"screen_identity_use_another_device" = "Use another device"; "screen_login_subtitle" = "Matrix แƒแƒ แƒ˜แƒก แƒฆแƒ˜แƒ แƒฅแƒกแƒ”แƒšแƒ˜ แƒฃแƒกแƒแƒคแƒ แƒ—แƒฎแƒ, แƒ“แƒ”แƒชแƒ”แƒœแƒขแƒ แƒแƒšแƒ˜แƒ–แƒ”แƒ‘แƒฃแƒšแƒ˜ แƒ™แƒแƒ›แƒฃแƒœแƒ˜แƒ™แƒแƒชแƒ˜แƒ˜แƒกแƒ—แƒ•แƒ˜แƒก."; "screen_qr_code_login_invalid_scan_state_retry_button" = "แƒฎแƒ”แƒšแƒแƒฎแƒšแƒ แƒชแƒ“แƒ"; "screen_report_content_block_user" = "แƒ›แƒแƒ›แƒฎแƒ›แƒแƒ แƒ”แƒ‘แƒšแƒ˜แƒก แƒ“แƒแƒ‘แƒšแƒแƒ™แƒ•แƒ"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "แƒ’แƒแƒ›แƒแƒกแƒ•แƒšแƒ"; "screen_signout_confirmation_dialog_title" = "แƒ’แƒแƒ›แƒแƒกแƒ•แƒšแƒ"; "screen_signout_preference_item" = "แƒ’แƒแƒ›แƒแƒกแƒ•แƒšแƒ"; -"screen_waitlist_message_success" = "แƒ™แƒ”แƒ—แƒ˜แƒšแƒ˜ แƒ˜แƒงแƒแƒก แƒ—แƒฅแƒ•แƒ”แƒœแƒ˜ แƒ›แƒแƒ‘แƒ แƒซแƒแƒœแƒ”แƒ‘แƒ %1$@-แƒจแƒ˜!"; diff --git a/ElementX/Resources/Localizations/ka.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/ka.lproj/Localizable.stringsdict index 715826477f..e7051408c9 100644 --- a/ElementX/Resources/Localizations/ka.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/ka.lproj/Localizable.stringsdict @@ -194,6 +194,22 @@ แƒแƒ แƒแƒกแƒฌแƒแƒ แƒ˜ PIN. แƒ—แƒฅแƒ•แƒ”แƒœ %1$d แƒจแƒแƒœแƒกแƒ˜ แƒ“แƒแƒ’แƒ แƒฉแƒแƒ— + 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 diff --git a/ElementX/Resources/Localizations/nl.lproj/InfoPlist.strings b/ElementX/Resources/Localizations/nl.lproj/InfoPlist.strings new file mode 100644 index 0000000000..2942fd2c91 --- /dev/null +++ b/ElementX/Resources/Localizations/nl.lproj/InfoPlist.strings @@ -0,0 +1,5 @@ +"NSCameraUsageDescription" = "Om foto's of video's te maken en deze als bericht te verzenden, heeft Element X toegang tot de camera nodig."; +"NSFaceIDUsageDescription" = "Face ID wordt gebruikt om toegang te krijgen tot je app."; +"NSLocationWhenInUseUsageDescription" = "Geef toegang tot je locatie, zodat Element X je locatie kan delen."; +"NSMicrophoneUsageDescription" = "Om berichten met audio op te nemen en te verzenden, heeft Element X toegang tot de microfoon nodig."; +"NSPhotoLibraryUsageDescription" = "Maakt het mogelijk om foto's en video's op te slaan in je bibliotheek."; diff --git a/ElementX/Resources/Localizations/nl.lproj/Localizable.strings b/ElementX/Resources/Localizations/nl.lproj/Localizable.strings new file mode 100644 index 0000000000..b340743bc5 --- /dev/null +++ b/ElementX/Resources/Localizations/nl.lproj/Localizable.strings @@ -0,0 +1,1015 @@ +"Notification" = "Melding"; +"a11y_delete" = "Verwijderen"; +"a11y_hide_password" = "Wachtwoord verbergen"; +"a11y_jump_to_bottom" = "Spring naar einde"; +"a11y_notifications_mentions_only" = "Alleen vermeldingen"; +"a11y_notifications_muted" = "Gedempt"; +"a11y_page_n" = "Pagina %1$d"; +"a11y_pause" = "Pauzeren"; +"a11y_pin_field" = "PIN-veld"; +"a11y_play" = "Afspelen"; +"a11y_poll" = "Peiling"; +"a11y_poll_end" = "Beeรฏndigde peiling"; +"a11y_react_with" = "Reageer met %1$@"; +"a11y_react_with_other_emojis" = "Reageer met andere emoji's"; +"a11y_read_receipts_multiple" = "Gelezen door %1$@ en %2$@"; +"a11y_read_receipts_single" = "Gelezen door %1$@"; +"a11y_read_receipts_tap_to_show_all" = "Tik om alles weer te geven"; +"a11y_remove_reaction_with" = "Verwijder reactie met %1$@"; +"a11y_send_files" = "Bestanden verzenden"; +"a11y_show_password" = "Wachtwoord weergeven"; +"a11y_start_call" = "Begin een oproep"; +"a11y_user_menu" = "Gebruikersmenu"; +"a11y_voice_message_record" = "Spraakbericht opnemen."; +"a11y_voice_message_stop_recording" = "Opnemen stoppen"; +"action_accept" = "Accepteren"; +"action_add_to_timeline" = "Toevoegen aan tijdlijn"; +"action_back" = "Terug"; +"action_call" = "Bellen"; +"action_cancel" = "Annuleren"; +"action_cancel_for_now" = "Cancel for now"; +"action_choose_photo" = "Kies foto"; +"action_clear" = "Wissen"; +"action_close" = "Sluiten"; +"action_complete_verification" = "Verificatie voltooien"; +"action_confirm" = "Bevestigen"; +"action_confirm_password" = "Confirm password"; +"action_continue" = "Voortzetten"; +"action_copy" = "Kopiรซren"; +"action_copy_link" = "Kopieer link"; +"action_copy_link_to_message" = "Kopieer link naar bericht"; +"action_create" = "Aanmaken"; +"action_create_a_room" = "Creรซer een kamer"; +"action_deactivate" = "Deactivate"; +"action_decline" = "Weigeren"; +"action_delete_poll" = "Peiling verwijderen"; +"action_disable" = "Uitschakelen"; +"action_discard" = "Verwerpen"; +"action_done" = "Gereed"; +"action_edit" = "Bewerken"; +"action_edit_poll" = "Peiling wijzigen"; +"action_enable" = "Activeren"; +"action_end_poll" = "Peiling beรซindigen"; +"action_enter_pin" = "Voer pincode in"; +"action_forgot_password" = "Wachtwoord vergeten?"; +"action_forward" = "Doorsturen"; +"action_go_back" = "Terug"; +"action_invite" = "Uitnodigen"; +"action_invite_friends" = "Mensen uitnodigen"; +"action_invite_friends_to_app" = "Nodig mensen uit voor %1$@"; +"action_invite_people_to_app" = "Nodig mensen uit voor %1$@"; +"action_invites_list" = "Uitnodigingen"; +"action_join" = "Deelnemen"; +"action_learn_more" = "Meer informatie"; +"action_leave" = "Verlaten"; +"action_leave_conversation" = "Gesprek verlaten"; +"action_leave_room" = "Ruimte verlaten"; +"action_manage_account" = "Account beheren"; +"action_manage_devices" = "Apparaten beheren"; +"action_message" = "Bericht"; +"action_next" = "Volgende"; +"action_no" = "Nee"; +"action_not_now" = "Niet nu"; +"action_ok" = "OK"; +"action_open_settings" = "Instellingen"; +"action_open_with" = "Openen met"; +"action_pin" = "Pin"; +"action_quick_reply" = "Snel antwoord"; +"action_quote" = "Citeren"; +"action_react" = "Reageren"; +"action_reject" = "Reject"; +"action_remove" = "Verwijderen"; +"action_reply" = "Antwoorden"; +"action_reply_in_thread" = "Antwoord in subchat"; +"action_report_bug" = "Probleem melden"; +"action_report_content" = "Inhoud melden"; +"action_reset" = "Opnieuw instellen"; +"action_reset_identity" = "Reset identity"; +"action_retry" = "Opnieuw proberen"; +"action_retry_decryption" = "Decryptie opnieuw proberen"; +"action_save" = "Opslaan"; +"action_search" = "Zoeken"; +"action_send" = "Verzenden"; +"action_send_message" = "Bericht verzenden"; +"action_share" = "Delen"; +"action_share_link" = "Link delen"; +"action_sign_in_again" = "Log opnieuw in"; +"action_signout" = "Uitloggen"; +"action_signout_anyway" = "Toch uitloggen"; +"action_skip" = "Overslaan"; +"action_start" = "Starten"; +"action_start_chat" = "Chat starten"; +"action_start_verification" = "Verificatie starten"; +"action_static_map_load" = "Tik om kaart te laden"; +"action_take_photo" = "Foto maken"; +"action_tap_for_options" = "Tik voor opties"; +"action_try_again" = "Probeer het opnieuw"; +"action_unpin" = "Unpin"; +"action_view_in_timeline" = "View in timeline"; +"action_view_source" = "Bron weergeven"; +"action_yes" = "Ja"; +"action.load_more" = "Meer laden"; +"action_deactivate_account" = "Deactivate account"; +"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" = "Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices."; +"banner.set_up_recovery.title" = "Set up recovery"; +"common_about" = "Over"; +"common_acceptable_use_policy" = "Beleid inzake redelijk gebruik"; +"common_advanced_settings" = "Geavanceerde instellingen"; +"common_analytics" = "Gebruiksgegevens"; +"common_appearance" = "Weergave"; +"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"; +"common_creating_room" = "Kamer maken..."; +"common_current_user_left_room" = "Heeft de kamer verlaten"; +"common_dark" = "Donker"; +"common_decryption_error" = "Decryptie fout"; +"common_developer_options" = "Ontwikkelaarsopties"; +"common_direct_chat" = "Directe chat"; +"common_edited_suffix" = "(bewerkt)"; +"common_editing" = "Bewerken"; +"common_emote" = "* %1$@ %2$@"; +"common_encryption_enabled" = "Encryptie ingeschakeld"; +"common_enter_your_pin" = "Voer je pincode in"; +"common_error" = "Fout"; +"common_everyone" = "Iedereen"; +"common_face_id_ios" = "Face ID"; +"common_failed" = "Mislukt"; +"common_favourite" = "Favoriet"; +"common_favourited" = "Favoriet gemarkeerd"; +"common_file" = "Bestand"; +"common_forward_message" = "Bericht doorsturen"; +"common_gif" = "GIF"; +"common_image" = "Afbeelding"; +"common_in_reply_to" = "Als antwoord op %1$@"; +"common_invite_unknown_profile" = "Deze Matrix-ID kan niet worden gevonden, dus de uitnodiging is mogelijk niet ontvangen."; +"common_leaving_room" = "De kamer verlaten"; +"common_light" = "Licht"; +"common_link_copied_to_clipboard" = "Link gekopieerd naar klembord"; +"common_loading" = "Laden..."; +"common_message" = "Bericht"; +"common_message_actions" = "Berichtacties"; +"common_message_layout" = "Berichtindeling"; +"common_message_removed" = "Bericht verwijderd"; +"common_modern" = "Modern"; +"common_mute" = "Dempen"; +"common_no_results" = "Geen resultaten"; +"common_offline" = "Offline"; +"common_optic_id_ios" = "Optic ID"; +"common_or" = "of"; +"common_password" = "Wachtwoord"; +"common_people" = "Personen"; +"common_permalink" = "Permalink"; +"common_permission" = "Toestemming"; +"common_please_wait" = "Even geduld..."; +"common_poll_total_votes" = "Totaal aantal stemmen: %1$@"; +"common_poll_undisclosed_text" = "Resultaten worden getoond nadat de peiling is afgelopen"; +"common_privacy_policy" = "Privacybeleid"; +"common_reaction" = "Reactie"; +"common_reactions" = "Reacties"; +"common_recovery_key" = "Herstelsleutel"; +"common_refreshing" = "Verversen..."; +"common_replying_to" = "Reageren op %1$@"; +"common_report_a_bug" = "Een fout melden"; +"common_report_a_problem" = "Meld een probleem"; +"common_report_submitted" = "Melding ingediend"; +"common_rich_text_editor" = "Uitgebreide tekstverwerker"; +"common_room" = "Kamer"; +"common_room_name" = "Naam van de kamer"; +"common_room_name_placeholder" = "bijv. de naam van je project"; +"common_saved_changes" = "Wijzigingen opgeslagen"; +"common_saving" = "Opslaan"; +"common_screen_lock" = "Schermvergrendeling"; +"common_search_for_someone" = "Iemand zoeken"; +"common_search_results" = "Zoekresultaten"; +"common_security" = "Beveiliging"; +"common_seen_by" = "Gezien door"; +"common_sending" = "Verzendenโ€ฆ"; +"common_sending_failed" = "Verzenden mislukt"; +"common_sent" = "Verzonden"; +"common_server_not_supported" = "Server niet ondersteund"; +"common_server_url" = "Server-URL"; +"common_settings" = "Instellingen"; +"common_shared_location" = "Gedeelde locatie"; +"common_signing_out" = "Uitloggen"; +"common_starting_chat" = "Chat startenโ€ฆ"; +"common_sticker" = "Sticker"; +"common_success" = "Geslaagd"; +"common_suggestions" = "Suggesties"; +"common_syncing" = "Synchroniseren"; +"common_system" = "Systeem"; +"common_text" = "Tekst"; +"common_third_party_notices" = "Kennisgevingen van derden"; +"common_thread" = "Subchat"; +"common_topic" = "Onderwerp"; +"common_topic_placeholder" = "Waar gaat deze kamer over?"; +"common_touch_id_ios" = "Touch ID"; +"common_unable_to_decrypt" = "Kan niet ontsleutelen"; +"common_unable_to_invite_message" = "Uitnodigingen konden niet naar een of meerdere gebruikers worden verzonden."; +"common_unable_to_invite_title" = "Kan uitnodiging(en) niet verzenden"; +"common_unlock" = "Ontgrendelen"; +"common_unmute" = "Dempen opheffen"; +"common_unsupported_event" = "Niet-ondersteunde gebeurtenis"; +"common_username" = "Gebruikersnaam"; +"common_verification_cancelled" = "Verificatie geannuleerd"; +"common_verification_complete" = "Verificatie voltooid"; +"common_video" = "Video"; +"common_voice_message" = "Spraakbericht"; +"common_waiting" = "Wachtenโ€ฆ"; +"common_waiting_for_decryption_key" = "Wachten op dit bericht"; +"common.do_not_show_this_again" = "Do not show this again"; +"common.open_source_licenses" = "Open source licenses"; +"common.pinned" = "Pinned"; +"common.send_to" = "Send to"; +"common_no_room_name" = "Geen kamernaam"; +"common_poll_end_confirmation" = "Weet je zeker dat je deze peiling wilt beรซindigen?"; +"common_poll_summary" = "Peiling: %1$@"; +"common_something_went_wrong" = "Er is iets misgegaan"; +"common_unable_to_decrypt_no_access" = "Je hebt geen toegang tot dit bericht"; +"common_verify_device" = "Apparaat verifiรซren"; +"confirm_recovery_key_banner_message" = "Je chatback-up is momenteel niet gesynchroniseerd. Je moet je herstelsleutel invoeren om toegang te behouden tot je chatback-up."; +"confirm_recovery_key_banner_title" = "Voer je herstelsleutel in"; +"crash_detection_dialog_content" = "%1$@ crashte de laatste keer dat het werd gebruikt. Wil je een crashrapport met ons delen?"; +"dialog_permission_camera" = "Geef toestemming in de systeeminstellingen om de applicatie de camera te laten gebruiken."; +"dialog_permission_generic" = "Geef hiervoor toestemming in de systeeminstellingen."; +"dialog_permission_location_description_ios" = "Verleen toegang via Instellingen -> Locatie."; +"dialog_permission_location_title_ios" = "%1$@ heeft geen toegang tot je locatie."; +"dialog_permission_microphone" = "Geef toestemming in de systeeminstellingen om de applicatie de microfoon te laten gebruiken."; +"dialog_permission_microphone_description_ios" = "Verleen toegang zodat je berichten met audio kunt opnemen en verzenden."; +"dialog_permission_microphone_title_ios" = "%1$@ heeft toegang tot je microfoon nodig."; +"dialog_permission_notification" = "Geef toestemming in de systeeminstellingen om de applicatie meldingen te laten weergeven."; +"dialog_title_confirmation" = "Bevestiging"; +"dialog_title_warning" = "Waarschuwing"; +"dialog_unsaved_changes_description_ios" = "Je wijzigingen worden niet opgeslagen"; +"dialog_unsaved_changes_title" = "Wijzigingen opslaan?"; +"emoji_picker_category_activity" = "Activiteiten"; +"emoji_picker_category_flags" = "Vlaggen"; +"emoji_picker_category_foods" = "Eten & Drinken"; +"emoji_picker_category_nature" = "Dieren & Natuur"; +"emoji_picker_category_objects" = "Voorwerpen"; +"emoji_picker_category_people" = "Smileys & Mensen"; +"emoji_picker_category_places" = "Reizen & Locaties"; +"emoji_picker_category_symbols" = "Symbolen"; +"error_account_creation_not_possible" = "Your homeserver needs to be upgraded to support Matrix Authentication Service and account creation."; +"error_failed_creating_the_permalink" = "Het aanmaken van de permanente link is mislukt"; +"error_failed_loading_map" = "%1$@ kon de kaart niet laden. Probeer het later opnieuw."; +"error_failed_loading_messages" = "Het laden van berichten is mislukt"; +"error_failed_locating_user" = "%1$@ had geen toegang tot je locatie. Probeer het later opnieuw."; +"error_failed_uploading_voice_message" = "Het uploaden van je spraakbericht is mislukt."; +"error_message_not_found" = "Bericht niet gevonden"; +"error_no_compatible_app_found" = "Er is geen compatibele app gevonden om deze actie uit te voeren."; +"error_some_messages_have_not_been_sent" = "Sommige berichten zijn niet verzonden"; +"error_unknown" = "Sorry, er is een fout opgetreden"; +"event_shield_reason_authenticity_not_guaranteed" = "The authenticity of this encrypted message can't be guaranteed on this device."; +"event_shield_reason_previously_verified" = "Encrypted by a previously-verified user."; +"event_shield_reason_sent_in_clear" = "Not encrypted."; +"event_shield_reason_unknown_device" = "Encrypted by an unknown or deleted device."; +"event_shield_reason_unsigned_device" = "Encrypted by a device not verified by its owner."; +"event_shield_reason_unverified_identity" = "Encrypted by an unverified user."; +"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_title" = "Enhance your call experience"; +"invite_friends_rich_title" = "๐Ÿ”๏ธ Sluit je bij mij aan op %1$@"; +"invite_friends_text" = "Hรฉ, praat met me op %1$@: %2$@"; +"leave_conversation_alert_subtitle" = "Weet je zeker dat je dit gesprek wilt verlaten? Dit gesprek is niet openbaar en je kunt niet opnieuw deelnemen zonder een uitnodiging."; +"leave_room_alert_empty_subtitle" = "Weet je zeker dat je deze kamer wilt verlaten? Je bent de enige persoon hier. Als je weggaat, kan er in de toekomst niemand meer toetreden, ook jij niet."; +"leave_room_alert_private_subtitle" = "Weet je zeker dat je deze kamer wilt verlaten? Deze kamer is niet openbaar en je kunt niet opnieuw deelnemen zonder een uitnodiging."; +"leave_room_alert_subtitle" = "Weet je zeker dat je de kamer wilt verlaten?"; +"login_initial_device_name_ios" = "%1$@ iOS"; +"notification_channel_call" = "Bellen"; +"notification_channel_listening_for_events" = "Wachten op gebeurtenissen"; +"notification_channel_noisy" = "Luide meldingen"; +"notification_channel_ringing_calls" = "Ringing calls"; +"notification_channel_silent" = "Stille meldingen"; +"notification_incoming_call" = "Incoming call"; +"notification_inline_reply_failed" = "** Verzenden is mislukt - open de kamer"; +"notification_invitation_action_reject" = "Afwijzen"; +"notification_invite_body" = "Nodigde je uit om te chatten"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; +"notification_mentioned_you_body" = "Heeft je genoemd: %1$@"; +"notification_new_messages" = "Nieuwe berichten"; +"notification_reaction_body" = "Reageerde met %1$@"; +"notification_room_invite_body" = "Nodigde je uit om tot de kamer toe te treden"; +"notification_room_invite_body_with_sender" = "%1$@ invited you to join the room"; +"notification_sender_me" = "Mij"; +"notification_sender_mention_reply" = "%1$@ mentioned or replied"; +"notification_test_push_notification_content" = "Je bekijkt de melding! Klik hier!"; +"notification_ticker_text_dm" = "%1$@: %2$@"; +"notification_ticker_text_group" = "%1$@: %2$@ %3$@"; +"notification_unread_notified_messages_and_invitation" = "%1$@ en %2$@"; +"notification_unread_notified_messages_in_room" = "%1$@ in %2$@"; +"notification_unread_notified_messages_in_room_and_invitation" = "%1$@ in %2$@ en %3$@"; +"preference_rageshake" = "Schudden om een bug te melden"; +"rageshake_detection_dialog_content" = "Het lijkt erop dat je gefrustreerd de telefoon hebt geschud. Wil je het scherm openen om een bug te rapporteren?"; +"rich_text_editor_bullet_list" = "Lijst met opsommingstekens in-/uitschakelen"; +"rich_text_editor_close_formatting_options" = "Opmaakopties sluiten"; +"rich_text_editor_code_block" = "Codeblok in-/uitschakelen"; +"rich_text_editor_composer_placeholder" = "Bericht..."; +"rich_text_editor_create_link" = "Maak een link"; +"rich_text_editor_edit_link" = "Link bewerken"; +"rich_text_editor_format_bold" = "Vetgedrukte opmaak toepassen"; +"rich_text_editor_format_italic" = "Cursieve opmaak toepassen"; +"rich_text_editor_format_strikethrough" = "Doorgestreepte opmaak toepassen"; +"rich_text_editor_format_underline" = "Onderstreepte opmaak toepassen"; +"rich_text_editor_full_screen_toggle" = "Modus volledig scherm in-/uitschakelen"; +"rich_text_editor_indent" = "Inspringen"; +"rich_text_editor_inline_code" = "Inline code-opmaak toepassen"; +"rich_text_editor_link" = "Link instellen"; +"rich_text_editor_numbered_list" = "Genummerde lijst in-/uitschakelen"; +"rich_text_editor_open_compose_options" = "Open opstelopties"; +"rich_text_editor_quote" = "Citaat in-/uitschakelen"; +"rich_text_editor_remove_link" = "Link verwijderen"; +"rich_text_editor_unindent" = "Inspringing ongedaan maken"; +"rich_text_editor_url_placeholder" = "Link"; +"rich_text_editor_a11y_add_attachment" = "Bijlage toevoegen"; +"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_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_pinned_timeline_screen_title_empty" = "Pinned messages"; +"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" = "Stuur een melding naar de hele kamer"; +"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_details_pinned_events_row_title" = "Pinned messages"; +"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_account_provider_change" = "Wijzig accountprovider"; +"screen_account_provider_form_hint" = "Homeserver-adres"; +"screen_account_provider_form_notice" = "Voer een zoekterm of een domeinnaam in."; +"screen_account_provider_form_subtitle" = "Zoek naar een bedrijf, community of privรฉserver."; +"screen_account_provider_form_title" = "Vind een accountprovider"; +"screen_account_provider_signin_title" = "Je staat op het punt om je aan te melden bij %@"; +"screen_account_provider_signup_title" = "Je staat op het punt een account aan te maken op %@"; +"screen_advanced_settings_developer_mode" = "Ontwikkelaarsmodus"; +"screen_advanced_settings_developer_mode_description" = "Schakel in om toegang te krijgen tot tools en functies voor ontwikkelaars."; +"screen_advanced_settings_rich_text_editor_description" = "Schakel de uitgebreide tekstverwerker uit om Markdown handmatig te typen."; +"screen_advanced_settings_send_read_receipts" = "Leesbevestigingen"; +"screen_advanced_settings_send_read_receipts_description" = "Indien uitgeschakeld worden er geen leesbevestigingen verstuurd. Je ontvangt nog steeds leesbevestigingen van andere gebruikers."; +"screen_advanced_settings_share_presence" = "Aanwezigheid delen"; +"screen_advanced_settings_share_presence_description" = "Indien uitgeschakeld kun je geen leesbevestigingen en typmeldingen verzenden of ontvangen."; +"screen_advanced_settings_view_source_description" = "Schakel optie in om de berichtbron in de tijdlijn te bekijken."; +"screen_analytics_prompt_data_usage" = "We zullen geen persoonlijke gegevens registreren of er een profiel van maken"; +"screen_analytics_prompt_help_us_improve" = "Deel anonieme gebruiksgegevens om ons te helpen problemen te identificeren."; +"screen_analytics_prompt_read_terms" = "Je kunt al onze voorwaarden %1$@ lezen."; +"screen_analytics_prompt_read_terms_content_link" = "hier"; +"screen_analytics_prompt_settings" = "Je kunt dit op elk moment uitschakelen"; +"screen_analytics_prompt_third_party_sharing" = "We delen je gegevens niet met derden"; +"screen_analytics_prompt_title" = "Help %1$@ te verbeteren"; +"screen_analytics_settings_share_data" = "Gebruiksgegevens delen"; +"screen_app_lock_biometric_authentication" = "biometrische authenticatie"; +"screen_app_lock_biometric_unlock" = "biometrische ontgrendeling"; +"screen_app_lock_biometric_unlock_reason_ios" = "Authenticatie is nodig om toegang te krijgen tot je app"; +"screen_app_lock_forgot_pin" = "Pincode vergeten?"; +"screen_app_lock_settings_change_pin" = "Pincode wijzigen"; +"screen_app_lock_settings_enable_biometric_unlock" = "Biometrische ontgrendeling toestaan"; +"screen_app_lock_settings_enable_face_id_ios" = "Face ID toestaan"; +"screen_app_lock_settings_enable_optic_id_ios" = "Optic ID toestaan"; +"screen_app_lock_settings_enable_touch_id_ios" = "Touch ID toestaan"; +"screen_app_lock_settings_remove_pin" = "Pincode verwijderen"; +"screen_app_lock_settings_remove_pin_alert_message" = "Weet je zeker dat je de pincode wilt verwijderen?"; +"screen_app_lock_settings_remove_pin_alert_title" = "Pincode verwijderen?"; +"screen_app_lock_setup_biometric_unlock_allow_title" = "%1$@ toestaan"; +"screen_app_lock_setup_biometric_unlock_skip" = "Ik gebruik liever een pincode"; +"screen_app_lock_setup_biometric_unlock_subtitle" = "Bespaar jezelf tijd en gebruik %1$@ om de app elke keer te ontgrendelen"; +"screen_app_lock_setup_choose_pin" = "Kies je pincode"; +"screen_app_lock_setup_confirm_pin" = "Bevestig pincode"; +"screen_app_lock_setup_pin_context" = "Vergrendel %1$@ om je chats extra te beveiligen.\n\nKies iets dat je kunt onthouden. Als je deze pincode vergeet, word je uitgelogd bij de app."; +"screen_app_lock_setup_pin_forbidden_dialog_content" = "Vanwege veiligheidsredenen kun je dit niet als je pincode kiezen"; +"screen_app_lock_setup_pin_forbidden_dialog_title" = "Kies een andere pincode"; +"screen_app_lock_setup_pin_mismatch_dialog_content" = "Voer dezelfde pincode twee keer in"; +"screen_app_lock_setup_pin_mismatch_dialog_title" = "Pincodes komen niet overeen"; +"screen_app_lock_signout_alert_message" = "Je moet opnieuw inloggen en een nieuwe pincode aanmaken om verder te gaan"; +"screen_app_lock_signout_alert_title" = "Je wordt uitgelogd"; +"screen_blocked_users_empty" = "Je hebt geen geblokkeerde gebruikers."; +"screen_blocked_users_unblocking" = "Deblokkeren..."; +"screen_bug_report_attach_screenshot" = "Schermafbeelding bijvoegen"; +"screen_bug_report_contact_me" = "Je mag contact met mij opnemen als je nog vervolg vragen hebt."; +"screen_bug_report_contact_me_title" = "Neem contact met mij op"; +"screen_bug_report_edit_screenshot" = "Schermafbeelding bewerken"; +"screen_bug_report_editor_description" = "Beschrijf het probleem. Wat heb je gedaan? Wat had je verwacht? Wat is er daadwerkelijk gebeurd. Beschrijf het zo gedetailleerd mogelijk."; +"screen_bug_report_editor_placeholder" = "Beschrijf het probleem..."; +"screen_bug_report_editor_supporting" = "Geeft de beschrijving in het Engels indien mogelijk."; +"screen_bug_report_error_description_too_short" = "De beschrijving is te kort, geef meer details over wat er is gebeurd. Bedankt!"; +"screen_bug_report_include_crash_logs" = "Crashlogboeken verzenden"; +"screen_bug_report_include_logs" = "Logboeken toestaan"; +"screen_bug_report_include_screenshot" = "Schermafbeelding verzenden"; +"screen_bug_report_logs_description" = "Er worden logbestanden bij uw bericht gevoegd om er zeker van te zijn dat alles goed werkt. Als u uw bericht zonder logbestanden wilt verzenden, schakelt u deze instelling uit."; +"screen_bug_report_view_logs" = "Logboeken weergeven"; +"screen_change_account_provider_matrix_org_subtitle" = "Matrix.org is een grote, gratis server op het openbare Matrix-netwerk voor veilige, gedecentraliseerde communicatie, beheerd door de Matrix.org Foundation."; +"screen_change_account_provider_other" = "Anders"; +"screen_change_account_provider_subtitle" = "Gebruik een andere accountprovider, zoals je eigen privรฉserver of een zakelijke account."; +"screen_change_account_provider_title" = "Wijzig accountprovider"; +"screen_change_server_error_invalid_homeserver" = "We konden deze homeserver niet bereiken. Controleer of je de homeserver-URL juist hebt ingevoerd. Als de URL juist is, neem dan contact op met de beheerder van je homeserver voor verdere hulp."; +"screen_change_server_error_invalid_well_known" = "Sliding sync is niet beschikbaar vanwege een probleem in het well-known bestand:\n%1$@"; +"screen_change_server_error_no_sliding_sync_message" = "Deze server ondersteunt op dit moment geen sliding sync."; +"screen_change_server_form_header" = "Homeserver-URL"; +"screen_change_server_form_notice" = "Je kunt alleen verbinding maken met een bestaande server die sliding sync ondersteunt. De beheerder van de homeserver moet dit configureren. %1$@"; +"screen_change_server_subtitle" = "Wat is het adres van je server?"; +"screen_change_server_title" = "Selecteer je server"; +"screen_chat_backup_key_backup_action_disable" = "Back-up uitschakelen"; +"screen_chat_backup_key_backup_action_enable" = "Back-up inschakelen"; +"screen_chat_backup_key_backup_description" = "Een back-up maken zorgt ervoor dat je je berichtgeschiedenis niet verliest. %1$@."; +"screen_chat_backup_key_backup_title" = "Back-up"; +"screen_chat_backup_recovery_action_change" = "Herstelsleutel wijzigen"; +"screen_chat_backup_recovery_action_confirm" = "Voer herstelsleutel in"; +"screen_chat_backup_recovery_action_confirm_description" = "Je chatback-up is momenteel niet gesynchroniseerd."; +"screen_chat_backup_recovery_action_setup" = "Herstelmogelijkheid instellen"; +"screen_chat_backup_recovery_action_setup_description" = "Krijg toegang tot je versleutelde berichten als je al je apparaten kwijtraakt of overal uit %1$@ bent uitgelogd."; +"screen_create_account_title" = "Create account"; +"screen_create_new_recovery_key_list_item_1" = "Open %1$@ op een desktopapparaat"; +"screen_create_new_recovery_key_list_item_2" = "Log opnieuw in op je account"; +"screen_create_new_recovery_key_list_item_3" = "Wanneer je wordt gevraagd om je apparaat te verifiรซren, selecteer %1$@"; +"screen_create_new_recovery_key_list_item_3_reset_all" = "โ€œAlles opnieuw instellenโ€"; +"screen_create_new_recovery_key_list_item_4" = "Volg de instructies om een nieuwe herstelsleutel te maken"; +"screen_create_new_recovery_key_list_item_5" = "Sla je nieuwe herstelsleutel op in een wachtwoordmanager of versleutelde notitie"; +"screen_create_new_recovery_key_title" = "Stel de versleuteling voor je account opnieuw in met een ander apparaat"; +"screen_create_poll_add_option_btn" = "Optie toevoegen"; +"screen_create_poll_anonymous_desc" = "Resultaten pas weergeven nadat de peiling is afgelopen"; +"screen_create_poll_anonymous_headline" = "Stemmen verbergen"; +"screen_create_poll_answer_hint" = "Optie %1$d"; +"screen_create_poll_cancel_confirmation_content_ios" = "Je wijzigingen worden niet opgeslagen"; +"screen_create_poll_cancel_confirmation_title_ios" = "Peiling annuleren"; +"screen_create_poll_question_desc" = "Vraag of onderwerp"; +"screen_create_poll_question_hint" = "Waar gaat de peiling over?"; +"screen_create_poll_title" = "Peiling maken"; +"screen_create_room_action_create_room" = "Nieuwe kamer"; +"screen_create_room_error_creating_room" = "Er is een fout opgetreden bij het aanmaken van de kamer"; +"screen_create_room_private_option_description" = "Berichten in deze kamer zijn versleuteld. Versleuteling kan achteraf niet worden uitgeschakeld."; +"screen_create_room_private_option_title" = "Privรฉ kamer (alleen op uitnodiging)"; +"screen_create_room_public_option_description" = "Berichten zijn niet versleuteld en iedereen kan ze lezen. Je kunt versleuteling later inschakelen."; +"screen_create_room_public_option_title" = "Openbare kamer (iedereen)"; +"screen_create_room_topic_label" = "Onderwerp (optioneel)"; +"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_edit_poll_delete_confirmation" = "Weet je zeker dat je deze peiling wilt verwijderen?"; +"screen_edit_profile_display_name" = "Weergavenaam"; +"screen_edit_profile_display_name_placeholder" = "Je weergavenaam"; +"screen_edit_profile_error" = "Er is een onbekende fout opgetreden en de informatie kon niet worden gewijzigd."; +"screen_edit_profile_error_title" = "Kan profiel niet bijwerken"; +"screen_edit_profile_title" = "Profiel bewerken"; +"screen_edit_profile_updating_details" = "Profiel bijwerkenโ€ฆ"; +"screen_encryption_reset_action_continue_reset" = "Continue reset"; +"screen_encryption_reset_bullet_1" = "Your account details, contacts, preferences, and chat list will be kept"; +"screen_encryption_reset_bullet_2" = "You will lose your existing message history"; +"screen_encryption_reset_bullet_3" = "You will need to verify all your existing devices and contacts again"; +"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_identity_confirmation_create_new_recovery_key" = "Maak een nieuwe herstelsleutel"; +"screen_identity_confirmation_subtitle" = "Verifieer dit apparaat om beveiligde berichten in te stellen."; +"screen_identity_confirmation_title" = "Bevestig dat jij het bent"; +"screen_identity_confirmation_use_another_device" = "Use another device"; +"screen_identity_confirmation_use_recovery_key" = "Use recovery key"; +"screen_identity_confirmed_subtitle" = "Nu kun je veilig berichten lezen of verzenden, en iedereen met wie je chat kan dit apparaat ook vertrouwen."; +"screen_identity_confirmed_title" = "Apparaat geverifieerd"; +"screen_identity_waiting_on_other_device" = "Wachten op ander apparaat..."; +"screen_invites_decline_chat_message" = "Weet je zeker dat je de uitnodiging om toe te treden tot %1$@ wilt weigeren?"; +"screen_invites_decline_chat_title" = "Uitnodiging weigeren"; +"screen_invites_decline_direct_chat_message" = "Weet je zeker dat je deze privรฉchat met %1$@ wilt weigeren?"; +"screen_invites_decline_direct_chat_title" = "Chat weigeren"; +"screen_invites_empty_list" = "Geen uitnodigingen"; +"screen_invites_invited_you" = "%1$@ (%2$@) heeft je uitgenodigd"; +"screen_join_room_join_action" = "Toetreden tot de kamer"; +"screen_join_room_knock_action" = "Klop om deel te nemen"; +"screen_join_room_space_not_supported_description" = "%1$@ ondersteunt nog geen spaces. Je kunt spaces benaderen via de webbrowser."; +"screen_join_room_space_not_supported_title" = "Spaces worden nog niet ondersteund"; +"screen_join_room_subtitle_knock" = "Klik op de knop hieronder en een kamerbeheerder wordt op de hoogte gebracht. Na goedkeuring kun je deelnemen aan het gesprek."; +"screen_join_room_subtitle_no_preview" = "Je moet lid zijn van deze kamer om de berichtgeschiedenis te bekijken."; +"screen_join_room_title_knock" = "Wil je tot deze kamer toetreden?"; +"screen_join_room_title_no_preview" = "Voorbeeld is niet beschikbaar"; +"screen_key_backup_disable_confirmation_action_turn_off" = "Uitschakelen"; +"screen_key_backup_disable_confirmation_description" = "Je verliest je versleutelde berichten als je bent uitgelogd op alle apparaten."; +"screen_key_backup_disable_confirmation_title" = "Weet je zeker dat je de back-up wilt uitschakelen?"; +"screen_key_backup_disable_description" = "Als je de back-up uitschakelt, verwijder je de back-up van je huidige versleuteling en schakel je andere beveiligingsfuncties uit. In dit geval zul je:"; +"screen_key_backup_disable_description_point_1" = "Geen berichtgeschiedenis hebben van versleutelde berichten op nieuwe apparaten"; +"screen_key_backup_disable_description_point_2" = "Toegang verliezen tot je versleutelde berichten als je overal uit %1$@ bent uitgelogd."; +"screen_key_backup_disable_title" = "Weet je zeker dat je de back-up wilt uitschakelen?"; +"screen_login_error_deactivated_account" = "Dit account is gedeactiveerd."; +"screen_login_error_invalid_credentials" = "Onjuiste gebruikersnaam en/of wachtwoord"; +"screen_login_error_invalid_user_id" = "Dit is geen geldige gebruikers-ID. Verwacht formaat: '@user:homeserver.org'"; +"screen_login_error_refresh_tokens" = "Deze server is geconfigureerd om verversingstokens te gebruiken. Deze worden niet ondersteund bij inloggen met een wachtwoord."; +"screen_login_error_unsupported_authentication" = "De geselecteerde homeserver ondersteunt geen wachtwoord of OIDC aanmelding. Neem contact op met je beheerder of kies een andere homeserver."; +"screen_login_form_header" = "Vul je gegevens in"; +"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."; +"screen_notification_optin_title" = "Sta meldingen toe en mis nooit meer een bericht"; +"screen_notification_settings_additional_settings_section_title" = "Aanvullende instellingen"; +"screen_notification_settings_calls_label" = "Audio- en videogesprekken"; +"screen_notification_settings_configuration_mismatch" = "Configuratie komt niet overeen"; +"screen_notification_settings_configuration_mismatch_description" = "We hebben de instellingen voor meldingen vereenvoudigd, zodat je de opties gemakkelijker kunt vinden. Sommige instellingen die je in het verleden hebt aangepast, worden hier niet getoond, maar zijn nog steeds actief.\n\nAls je doorgaat, kunnen sommige van je instellingen veranderen."; +"screen_notification_settings_direct_chats" = "Directe chats"; +"screen_notification_settings_edit_custom_settings_section_title" = "Aangepaste instelling per chat"; +"screen_notification_settings_edit_failed_updating_default_mode" = "Er is een fout opgetreden bij het bijwerken van de meldingsinstelling."; +"screen_notification_settings_edit_mode_all_messages" = "Alle berichten"; +"screen_notification_settings_edit_mode_mentions_and_keywords" = "Alleen vermeldingen en trefwoorden"; +"screen_notification_settings_edit_screen_direct_section_header" = "Bij directe chats, stuur me een melding voor"; +"screen_notification_settings_edit_screen_group_section_header" = "Bij groep chats, stuur me een melding voor"; +"screen_notification_settings_enable_notifications" = "Meldingen op dit apparaat inschakelen"; +"screen_notification_settings_failed_fixing_configuration" = "De configuratie is niet gecorrigeerd. Probeer het opnieuw."; +"screen_notification_settings_group_chats" = "Groep chats"; +"screen_notification_settings_invite_for_me_label" = "Uitnodigingen"; +"screen_notification_settings_mentions_only_disclaimer" = "Je homeserver ondersteunt deze optie niet in versleutelde kamers; in sommige kamers krijg je mogelijk geen meldingen."; +"screen_notification_settings_mentions_section_title" = "Vermeldingen"; +"screen_notification_settings_mode_all" = "Alles"; +"screen_notification_settings_mode_mentions" = "Vermeldingen"; +"screen_notification_settings_notification_section_title" = "Stuur me een melding voor"; +"screen_notification_settings_room_mention_label" = "Stuur me een melding bij @kamer"; +"screen_notification_settings_system_notifications_action_required" = "Wijzig je %1$@ om meldingen te ontvangen."; +"screen_notification_settings_system_notifications_action_required_content_link" = "systeeminstellingen"; +"screen_notification_settings_system_notifications_turned_off" = "Systeemmeldingen uitgeschakeld"; +"screen_notification_settings_title" = "Meldingen"; +"screen_onboarding_sign_in_manually" = "Handmatig inloggen"; +"screen_onboarding_sign_in_with_qr_code" = "Inloggen met QR-code"; +"screen_onboarding_sign_up" = "Account aanmaken"; +"screen_onboarding_welcome_message" = "Welkom bij de snelste %1$@ ooit. Supercharged, voor snelheid en eenvoud."; +"screen_onboarding_welcome_subtitle" = "Welkom bij %1$@. Supercharged, voor snelheid en eenvoud."; +"screen_onboarding_welcome_title" = "Wees in je element"; +"screen_polls_history_empty_ongoing" = "Kan geen actieve peilingen vinden."; +"screen_polls_history_empty_past" = "Kan geen eerdere peilingen vinden."; +"screen_polls_history_filter_ongoing" = "Actief"; +"screen_polls_history_filter_past" = "Afgelopen"; +"screen_polls_history_title" = "Peilingen"; +"screen_qr_code_login_connecting_subtitle" = "Een beveiligde verbinding tot stand brengen"; +"screen_qr_code_login_connection_note_secure_state_description" = "Er kon geen beveiligde verbinding worden gemaakt met het nieuwe apparaat. Je bestaande apparaten zijn nog steeds veilig en je hoeft je daarover geen zorgen te maken."; +"screen_qr_code_login_connection_note_secure_state_list_header" = "Wat nu?"; +"screen_qr_code_login_connection_note_secure_state_list_item_1" = "Probeer opnieuw in te loggen met een QR-code voor het geval dit een netwerkprobleem was"; +"screen_qr_code_login_connection_note_secure_state_list_item_2" = "Als je hetzelfde probleem ondervindt, probeer dan een ander wifi-netwerk of gebruik je mobiele data in plaats van wifi."; +"screen_qr_code_login_connection_note_secure_state_list_item_3" = "Als dat niet werkt, log dan handmatig in"; +"screen_qr_code_login_connection_note_secure_state_title" = "Verbinding niet veilig"; +"screen_qr_code_login_device_code_subtitle" = "Daar word je gevraagd om de twee cijfers in te voeren die op dit apparaat worden weergegeven."; +"screen_qr_code_login_device_code_title" = "Voer het onderstaande nummer in op je andere apparaat"; +"screen_qr_code_login_device_not_signed_in_scan_state_description" = "Sign in to your other device and then try again, or use another device thatโ€™s already signed in."; +"screen_qr_code_login_device_not_signed_in_scan_state_subtitle" = "Other device not signed in"; +"screen_qr_code_login_error_cancelled_subtitle" = "De aanmelding is geannuleerd op het andere apparaat."; +"screen_qr_code_login_error_cancelled_title" = "Login verzoek geannuleerd"; +"screen_qr_code_login_error_declined_subtitle" = "De aanmelding is geweigerd op het andere apparaat."; +"screen_qr_code_login_error_declined_title" = "Aanmelden geweigerd"; +"screen_qr_code_login_error_expired_subtitle" = "Aanmelden is verlopen. Probeer het opnieuw."; +"screen_qr_code_login_error_expired_title" = "De aanmelding was niet op tijd voltooid"; +"screen_qr_code_login_error_linking_not_suported_subtitle" = "Your other device does not support signing in to %@ with a QR code.\n\nTry signing in manually, or scan the QR code with another device."; +"screen_qr_code_login_error_linking_not_suported_title" = "QR-code wordt niet ondersteund"; +"screen_qr_code_login_error_sliding_sync_not_supported_subtitle" = "Your account provider does not support %1$@."; +"screen_qr_code_login_error_sliding_sync_not_supported_title" = "%1$@ not supported"; +"screen_qr_code_login_initial_state_button_title" = "Klaar om te scannen"; +"screen_qr_code_login_initial_state_item_1" = "Open %1$@ op een desktopapparaat"; +"screen_qr_code_login_initial_state_item_2" = "Klik op je afbeelding"; +"screen_qr_code_login_initial_state_item_3" = "Selecteer %1$@"; +"screen_qr_code_login_initial_state_item_3_action" = "โ€œNieuw apparaat koppelenโ€"; +"screen_qr_code_login_initial_state_item_4" = "Scan de QR-code met dit apparaat"; +"screen_qr_code_login_initial_state_title" = "Open %1$@ op een ander apparaat om de QR-code te krijgen"; +"screen_qr_code_login_invalid_scan_state_description" = "Gebruik de QR-code die op het andere apparaat wordt weergegeven."; +"screen_qr_code_login_invalid_scan_state_subtitle" = "Verkeerde QR-code"; +"screen_qr_code_login_no_camera_permission_button" = "Ga naar camera-instellingen"; +"screen_qr_code_login_no_camera_permission_state_description" = "Je moet %1$@ toestemming geven om de camera van je apparaat te gebruiken om verder te gaan."; +"screen_qr_code_login_no_camera_permission_state_title" = "Cameratoegang toestaan om de QR-code te scannen"; +"screen_qr_code_login_scanning_state_title" = "Scan de QR-code"; +"screen_qr_code_login_start_over_button" = "Opnieuw beginnen"; +"screen_qr_code_login_unknown_error_description" = "Er is een onverwachte fout opgetreden. Probeer het opnieuw."; +"screen_qr_code_login_verify_code_loading" = "Aan het wachten op je andere apparaat"; +"screen_qr_code_login_verify_code_subtitle" = "Je accountprovider kan om de volgende code vragen om de aanmelding te verifiรซren."; +"screen_qr_code_login_verify_code_title" = "Je verificatiecode"; +"screen_recovery_key_change_description" = "Maak een nieuwe herstelsleutel aan als je je bestaande kwijt bent. Nadat je je herstelsleutel hebt gewijzigd, werkt je oude herstelsleutel niet meer."; +"screen_recovery_key_change_generate_key" = "Genereer een nieuwe herstelsleutel"; +"screen_recovery_key_change_generate_key_description" = "Zorg ervoor dat je je herstelsleutel op een veilige plek kunt bewaren"; +"screen_recovery_key_change_success" = "Herstelsleutel gewijzigd"; +"screen_recovery_key_change_title" = "Herstelsleutel wijzigen?"; +"screen_recovery_key_confirm_create_new_recovery_key" = "Maak een nieuwe herstelsleutel"; +"screen_recovery_key_confirm_description" = "Zorg ervoor dat niemand dit scherm kan zien!"; +"screen_recovery_key_confirm_error_content" = "Probeer het opnieuw om toegang tot je chatback-up te bevestigen."; +"screen_recovery_key_confirm_error_title" = "Onjuiste herstelsleutel"; +"screen_recovery_key_confirm_key_description" = "Als je een beveiligingssleutel of beveiligingszin hebt, werkt dit ook."; +"screen_recovery_key_confirm_key_placeholder" = "Voer in..."; +"screen_recovery_key_confirm_lost_recovery_key" = "Herstelsleutel kwijt?"; +"screen_recovery_key_confirm_success" = "Herstelsleutel bevestigd"; +"screen_recovery_key_confirm_title" = "Voer je herstelsleutel in"; +"screen_recovery_key_copied_to_clipboard" = "Herstelsleutel gekopieerd"; +"screen_recovery_key_generating_key" = "Genereren..."; +"screen_recovery_key_save_action" = "Herstelsleutel opslaan"; +"screen_recovery_key_save_description" = "Noteer je herstelsleutel op een veilige plek of bewaar deze in een wachtwoordmanager."; +"screen_recovery_key_save_key_description" = "Tik om de herstelsleutel te kopiรซren"; +"screen_recovery_key_save_title" = "Sla je herstelsleutel op"; +"screen_recovery_key_setup_confirmation_description" = "Na deze stap kun je je nieuwe herstelsleutel niet meer inzien."; +"screen_recovery_key_setup_confirmation_title" = "Heb je je herstelsleutel opgeslagen?"; +"screen_recovery_key_setup_description" = "Je chatback-up wordt beschermd door een herstelsleutel. Als je na de installatie een nieuwe herstelsleutel nodig hebt, kun je deze opnieuw aanmaken door 'Herstelsleutel wijzigen' te selecteren."; +"screen_recovery_key_setup_generate_key" = "Genereer je herstelsleutel"; +"screen_recovery_key_setup_generate_key_description" = "Zorg ervoor dat je je herstelsleutel op een veilige plek kunt bewaren"; +"screen_recovery_key_setup_success" = "Herstelmogelijkheid succesvol ingesteld"; +"screen_recovery_key_setup_title" = "Herstelmogelijkheid instellen"; +"screen_report_content_block_user_hint" = "Vink aan als je alle huidige en toekomstige berichten van deze gebruiker wilt verbergen"; +"screen_report_content_explanation" = "Dit bericht wordt gerapporteerd aan de beheerder van je homeserver. Ze zullen geen versleutelde berichten kunnen lezen."; +"screen_report_content_hint" = "Reden voor het melden van deze inhoud"; +"screen_reset_encryption_confirmation_alert_action" = "Yes, reset now"; +"screen_reset_encryption_confirmation_alert_subtitle" = "This process is irreversible."; +"screen_reset_encryption_confirmation_alert_title" = "Are you sure you want to reset your identity?"; +"screen_reset_encryption_password_placeholder" = "Enterโ€ฆ"; +"screen_reset_encryption_password_subtitle" = "Confirm that you want to reset your identity."; +"screen_reset_encryption_password_title" = "Enter your account password to continue"; +"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_room_alias_resolver_resolve_alias_failure" = "Kan het kameradres niet vinden."; +"screen_room_attachment_source_camera" = "Camera"; +"screen_room_attachment_source_camera_video" = "Video opnemen"; +"screen_room_attachment_source_files" = "Bijlage"; +"screen_room_attachment_source_gallery" = "Foto & Video Bibliotheek"; +"screen_room_attachment_source_location" = "Locatie"; +"screen_room_attachment_source_poll" = "Peiling"; +"screen_room_attachment_text_formatting" = "Tekstopmaak"; +"screen_room_change_permissions_administrators" = "Alleen beheerders"; +"screen_room_change_permissions_ban_people" = "Personen verbannen"; +"screen_room_change_permissions_delete_messages" = "Berichten verwijderen"; +"screen_room_change_permissions_invite_people" = "Personen uitnodigen"; +"screen_room_change_permissions_moderators" = "Beheerders en moderators"; +"screen_room_change_permissions_remove_people" = "Personen verwijderen"; +"screen_room_change_permissions_room_avatar" = "Kamerafbeelding wijzigen"; +"screen_room_change_permissions_room_name" = "Kamernaam wijzigen"; +"screen_room_change_permissions_room_topic" = "Kameronderwerp wijzigen"; +"screen_room_change_permissions_send_messages" = "Berichten verzenden"; +"screen_room_change_role_administrators_title" = "Beheerders bewerken"; +"screen_room_change_role_confirm_add_admin_description" = "Je kunt deze actie niet ongedaan maken. Je bevordert deze gebruiker tot hetzelfde machtsniveau als jij."; +"screen_room_change_role_confirm_add_admin_title" = "Beheerder toevoegen?"; +"screen_room_change_role_confirm_demote_self_action" = "Degraderen"; +"screen_room_change_role_confirm_demote_self_description" = "Je kunt deze wijziging niet ongedaan maken omdat je jezelf degradeert. Als je de laatste gebruiker met bevoegdheden in de kamer bent, is het onmogelijk om deze bevoegdheden terug te krijgen."; +"screen_room_change_role_confirm_demote_self_title" = "Jezelf degraderen?"; +"screen_room_change_role_invited_member_name" = "%1$@ (In behandeling)"; +"screen_room_change_role_moderators_admin_section_footer" = "Beheerders hebben automatisch moderatorrechten"; +"screen_room_change_role_moderators_title" = "Moderators bewerken"; +"screen_room_change_role_unsaved_changes_description" = "Je hebt niet-opgeslagen wijzigingen"; +"screen_room_change_role_unsaved_changes_title" = "Wijzigingen opslaan?"; +"screen_room_details_add_topic_title" = "Onderwerp toevoegen"; +"screen_room_details_already_a_member" = "Reeds lid"; +"screen_room_details_already_invited" = "Reeds uitgenodigd"; +"screen_room_details_badge_encrypted" = "Versleuteld"; +"screen_room_details_badge_not_encrypted" = "Niet versleuteld"; +"screen_room_details_badge_public" = "Openbare kamer"; +"screen_room_details_edit_room_title" = "Kamer bewerken"; +"screen_room_details_edition_error" = "Er is een onbekende fout opgetreden en de informatie kon niet worden gewijzigd."; +"screen_room_details_edition_error_title" = "Kan kamer niet bijwerken"; +"screen_room_details_encryption_enabled_subtitle" = "Berichten zijn beveiligd met sloten. Alleen jij en de ontvangers hebben de unieke sleutels om ze te ontgrendelen."; +"screen_room_details_encryption_enabled_title" = "Berichtversleuteling ingeschakeld"; +"screen_room_details_error_loading_notification_settings" = "Er is een fout opgetreden bij het laden van de meldingsinstellingen."; +"screen_room_details_error_muting" = "Het dempen van deze kamer is mislukt. Probeer het opnieuw."; +"screen_room_details_error_unmuting" = "Het dempen opheffen voor deze kamer is mislukt. Probeer het opnieuw."; +"screen_room_details_notification_mode_custom" = "Aangepast"; +"screen_room_details_notification_mode_default" = "Standaard"; +"screen_room_details_notification_title" = "Meldingen"; +"screen_room_details_share_room_title" = "Kamer delen"; +"screen_room_details_title" = "Kamer info"; +"screen_room_details_updating_room" = "Kamer bijwerkenโ€ฆ"; +"screen_room_directory_search_loading_error" = "Laden mislukt"; +"screen_room_directory_search_title" = "Kamergids"; +"screen_room_encrypted_history_banner" = "Berichtgeschiedenis is momenteel niet beschikbaar."; +"screen_room_encrypted_history_banner_unverified" = "Berichtgeschiedenis is niet beschikbaar in deze kamer. Verifieer dit apparaat om je berichtgeschiedenis te bekijken."; +"screen_room_error_failed_retrieving_user_details" = "Kon gebruikersgegevens niet ophalen"; +"screen_room_invite_again_alert_message" = "Wil je ze terug uitnodigen?"; +"screen_room_invite_again_alert_title" = "Je bent alleen in deze chat"; +"screen_room_member_details_block_alert_action" = "Blokkeren"; +"screen_room_member_details_block_alert_description" = "Geblokkeerde gebruikers kunnen je geen berichten sturen en al hun berichten worden verborgen. Je kunt ze op elk moment deblokkeren."; +"screen_room_member_details_block_user" = "Gebruiker blokkeren"; +"screen_room_member_details_title" = "Profiel"; +"screen_room_member_details_unblock_alert_action" = "Deblokkeren"; +"screen_room_member_details_unblock_alert_description" = "Je zult alle berichten van hen weer kunnen zien."; +"screen_room_member_details_unblock_user" = "Gebruiker deblokkeren"; +"screen_room_member_list_ban_member_confirmation_action" = "Verbannen"; +"screen_room_member_list_ban_member_confirmation_description" = "Ze kunnen niet meer toetreden tot deze kamer als ze worden uitgenodigd."; +"screen_room_member_list_ban_member_confirmation_title" = "Weet je zeker dat je dit lid wilt verbannen?"; +"screen_room_member_list_banned_empty" = "Er zijn geen verbannen gebruikers in deze kamer."; +"screen_room_member_list_banning_user" = "%1$@ verbannen"; +"screen_room_member_list_manage_member_ban" = "Lid verwijderen en verbannen"; +"screen_room_member_list_manage_member_remove" = "Verwijderen uit kamer"; +"screen_room_member_list_manage_member_remove_confirmation_ban" = "Lid verwijderen en verbannen"; +"screen_room_member_list_manage_member_remove_confirmation_kick" = "Alleen lid verwijderen"; +"screen_room_member_list_manage_member_remove_confirmation_title" = "Lid verwijderen en toekomstige deelname verbieden?"; +"screen_room_member_list_manage_member_unban_action" = "Ontbannen"; +"screen_room_member_list_manage_member_unban_message" = "Ze kunnen opnieuw tot de kamer toetreden als ze worden uitgenodigd."; +"screen_room_member_list_manage_member_unban_title" = "Ontban gebruiker"; +"screen_room_member_list_manage_member_user_info" = "Profiel bekijken"; +"screen_room_member_list_mode_banned" = "Verbannen"; +"screen_room_member_list_mode_members" = "Leden"; +"screen_room_member_list_pending_header_title" = "In behandeling"; +"screen_room_member_list_removing_user" = "%1$@ wordt verwijderd..."; +"screen_room_member_list_role_administrator" = "Beheerder"; +"screen_room_member_list_role_moderator" = "Moderator"; +"screen_room_member_list_room_members_header_title" = "Kamerleden"; +"screen_room_member_list_unbanning_user" = "%1$@ ontbannen"; +"screen_room_notification_settings_allow_custom" = "Aanpassen toestaan"; +"screen_room_notification_settings_allow_custom_footnote" = "Als je dit inschakelt, wordt je standaardinstelling overschreven"; +"screen_room_notification_settings_custom_settings_title" = "Stuur me een melding in deze chat voor"; +"screen_room_notification_settings_default_setting_footnote" = "Je kunt het wijzigen in je %1$@."; +"screen_room_notification_settings_default_setting_footnote_content_link" = "algemene instellingen"; +"screen_room_notification_settings_default_setting_title" = "Standaardinstelling"; +"screen_room_notification_settings_edit_remove_setting" = "Aanpassingen verwijderen"; +"screen_room_notification_settings_error_loading_settings" = "Er is een fout opgetreden bij het laden van de meldingsinstellingen."; +"screen_room_notification_settings_error_restoring_default" = "Het herstellen van de standaardmeldingen is mislukt. Probeer het opnieuw."; +"screen_room_notification_settings_error_setting_mode" = "Het instellen van de meldingen is mislukt. Probeer het opnieuw."; +"screen_room_notification_settings_mentions_only_disclaimer" = "Je homeserver ondersteunt deze optie niet in versleutelde kamers; in deze kamer krijg je geen meldingen."; +"screen_room_notification_settings_mode_all_messages" = "Alle berichten"; +"screen_room_notification_settings_room_custom_settings_title" = "In deze kamer, stuur me een melding voor"; +"screen_room_retry_send_menu_send_again_action" = "Opnieuw verzenden"; +"screen_room_retry_send_menu_title" = "Je bericht is niet verzonden"; +"screen_room_roles_and_permissions_admins" = "Beheerders"; +"screen_room_roles_and_permissions_change_my_role" = "Mijn rol wijzigen"; +"screen_room_roles_and_permissions_change_role_demote_to_member" = "Degraderen tot lid"; +"screen_room_roles_and_permissions_change_role_demote_to_moderator" = "Degraderen tot moderator"; +"screen_room_roles_and_permissions_member_moderation" = "Moderatie van leden"; +"screen_room_roles_and_permissions_messages_and_content" = "Berichten en inhoud"; +"screen_room_roles_and_permissions_moderators" = "Moderators"; +"screen_room_roles_and_permissions_permissions_header" = "Rechten"; +"screen_room_roles_and_permissions_reset" = "Rechten opnieuw instellen"; +"screen_room_roles_and_permissions_reset_confirm_description" = "Als je de rechten opnieuw instelt, raak je de huidige instellingen kwijt."; +"screen_room_roles_and_permissions_reset_confirm_title" = "Rechten opnieuw instellen?"; +"screen_room_roles_and_permissions_roles_header" = "Rollen"; +"screen_room_roles_and_permissions_room_details" = "Kamergegevens"; +"screen_room_roles_and_permissions_title" = "Rollen en rechten"; +"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_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"; +"screen_room_timeline_reactions_show_less" = "Minder tonen"; +"screen_room_timeline_reactions_show_more" = "Meer tonen"; +"screen_room_timeline_read_marker_title" = "Nieuw"; +"screen_room_title" = "Chat"; +"screen_room_typing_many_members_first_component_ios" = "%1$@, %2$@ en "; +"screen_room_typing_notification_plural_ios" = " zijn aan het typen..."; +"screen_room_typing_notification_singular_ios" = " is aan het typen..."; +"screen_room_typing_two_members" = "%1$@ en %2$@"; +"screen_room_voice_message_tooltip" = "Vasthouden om op te nemen"; +"screen_roomlist_a11y_create_message" = "Begin een nieuw gesprek of maak een nieuwe kamer"; +"screen_roomlist_empty_message" = "Ga aan de slag door iemand een bericht te sturen."; +"screen_roomlist_empty_title" = "Nog geen chats."; +"screen_roomlist_filter_favourites" = "Favorieten"; +"screen_roomlist_filter_favourites_empty_state_subtitle" = "Je kunt een chat toevoegen aan je favorieten in de chatinstellingen.\nVoor nu kun je filters deselecteren om je andere chats te zien"; +"screen_roomlist_filter_favourites_empty_state_title" = "Je hebt nog geen favoriete chats"; +"screen_roomlist_filter_invites" = "Uitnodigingen"; +"screen_roomlist_filter_invites_empty_state_title" = "Je hebt geen openstaande uitnodigingen."; +"screen_roomlist_filter_low_priority" = "Lage prioriteit"; +"screen_roomlist_filter_mixed_empty_state_subtitle" = "Je kunt filters deselecteren om je andere chats te zien"; +"screen_roomlist_filter_mixed_empty_state_title" = "Je hebt geen chats voor deze selectie"; +"screen_roomlist_filter_people_empty_state_title" = "Je hebt nog geen directe chats"; +"screen_roomlist_filter_rooms" = "Kamers"; +"screen_roomlist_filter_rooms_empty_state_title" = "Je zit nog niet in een kamer"; +"screen_roomlist_filter_unreads" = "Ongelezen"; +"screen_roomlist_filter_unreads_empty_state_title" = "Gefeliciteerd!\nJe hebt geen ongelezen berichten!"; +"screen_roomlist_main_space_title" = "Chats"; +"screen_roomlist_mark_as_read" = "Markeren als gelezen"; +"screen_roomlist_mark_as_unread" = "Markeren als ongelezen"; +"screen_roomlist_room_directory_button_title" = "Blader door alle kamers"; +"screen_server_confirmation_change_server" = "Accountprovider wijzigen"; +"screen_server_confirmation_message_login_element_dot_io" = "Een privรฉserver voor medewerkers van Element."; +"screen_server_confirmation_message_login_matrix_dot_org" = "Matrix is een open netwerk voor veilige, gedecentraliseerde communicatie."; +"screen_server_confirmation_message_register" = "Dit is waar je gesprekken zullen worden bewaard โ€” net zoals je een e-mailprovider zou gebruiken om je e-mails te bewaren."; +"screen_server_confirmation_title_login" = "Je staat op het punt je aan te melden bij %1$@"; +"screen_server_confirmation_title_register" = "Je staat op het punt een account aan te maken op %1$@"; +"screen_session_verification_cancelled_subtitle" = "Er lijkt iets niet goed te gaan. Of er is een time-out opgetreden of het verzoek is geweigerd."; +"screen_session_verification_compare_emojis_subtitle" = "Bevestig dat de emoji's hieronder overeenkomen met de emoji's in je andere sessie."; +"screen_session_verification_compare_emojis_title" = "Vergelijk emoji's"; +"screen_session_verification_compare_numbers_subtitle" = "Bevestig dat de onderstaande cijfers overeenkomen met de cijfers die worden weergegeven in je andere sessie."; +"screen_session_verification_compare_numbers_title" = "Vergelijk getallen"; +"screen_session_verification_complete_subtitle" = "Je nieuwe sessie is nu geverifieerd. Het heeft toegang tot je versleutelde berichten en andere gebruikers zullen het als vertrouwd beschouwen."; +"screen_session_verification_enter_recovery_key" = "Voer herstelsleutel in"; +"screen_session_verification_open_existing_session_subtitle" = "Bewijs dat jij het bent om toegang te krijgen tot je versleutelde berichtgeschiedenis."; +"screen_session_verification_open_existing_session_title" = "Open een bestaande sessie"; +"screen_session_verification_positive_button_canceled" = "Verificatie opnieuw proberen"; +"screen_session_verification_positive_button_initial" = "Ik ben er klaar voor"; +"screen_session_verification_positive_button_verifying_ongoing" = "Wachten om te vergelijken"; +"screen_session_verification_ready_subtitle" = "Vergelijk een unieke combinatie van emoji's."; +"screen_session_verification_request_accepted_subtitle" = "Vergelijk de unieke emoji's, ze dienen in dezelfde volgorde te worden weergegeven."; +"screen_session_verification_they_dont_match" = "Ze komen niet overeen"; +"screen_session_verification_they_match" = "Ze komen overeen"; +"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"; +"screen_share_my_location_action" = "Deel mijn locatie"; +"screen_share_open_apple_maps" = "Openen in Apple Maps"; +"screen_share_open_google_maps" = "Openen in Google Maps"; +"screen_share_open_osm_maps" = "Openen in OpenStreetMap"; +"screen_share_this_location_action" = "Deel deze locatie"; +"screen_signed_out_reason_1" = "Je hebt je wachtwoord gewijzigd in een andere sessie"; +"screen_signed_out_reason_2" = "Je hebt deze sessie verwijderd in een andere sessie"; +"screen_signed_out_reason_3" = "De beheerder van je server heeft je toegang ongeldig gemaakt"; +"screen_signed_out_subtitle" = "Je bent mogelijk uitgelogd om een van de onderstaande redenen. Meld je opnieuw aan om %@ te blijven gebruiken."; +"screen_signed_out_title" = "Je bent uitgelogd"; +"screen_signout_confirmation_dialog_content" = "Weet je zeker dat je je wilt uitloggen?"; +"screen_signout_in_progress_dialog_content" = "Uitloggen..."; +"screen_signout_key_backup_disabled_subtitle" = "Je staat op het punt uit te loggen bij je laatste sessie. Als je je nu uitlogt, verlies je de toegang tot je versleutelde berichten."; +"screen_signout_key_backup_disabled_title" = "Je hebt de back-up uitgeschakeld"; +"screen_signout_key_backup_offline_subtitle" = "De backup van je sleutels was nog bezig toen je offline ging. Maak opnieuw verbinding zodat er een back-up van je sleutels kan worden gemaakt voordat je uitlogt."; +"screen_signout_key_backup_offline_title" = "De backup van je sleutels is nog bezig"; +"screen_signout_key_backup_ongoing_subtitle" = "Wacht tot dit voltooid is voordat je uitlogt."; +"screen_signout_key_backup_ongoing_title" = "De backup van je sleutels is nog bezig"; +"screen_signout_recovery_disabled_subtitle" = "Je staat op het punt uit te loggen bij je laatste sessie. Als je je nu uitlogt, verlies je de toegang tot je versleutelde berichten."; +"screen_signout_recovery_disabled_title" = "Herstelmogelijkheid niet ingesteld"; +"screen_signout_save_recovery_key_subtitle" = "Je staat op het punt uit te loggen bij je laatste sessie. Als je je nu uitlogt, kan het dat je de toegang tot je versleutelde berichten verliest."; +"screen_signout_save_recovery_key_title" = "Heb je je herstelsleutel opgeslagen?"; +"screen_start_chat_error_starting_chat" = "Er is een fout opgetreden bij het starten van een chat"; +"screen_view_location_title" = "Locatie"; +"screen_welcome_bullet_1" = "Oproepen, peilingen, zoekopdrachten en meer zullen later dit jaar worden toegevoegd."; +"screen_welcome_bullet_2" = "Berichtgeschiedenis voor versleutelde kamers is nog niet beschikbaar."; +"screen_welcome_bullet_3" = "We horen graag van je, laat ons weten wat je ervan vindt via de instellingenpagina."; +"screen_welcome_button" = "Aan de slag!"; +"screen_welcome_subtitle" = "Dit is wat je moet weten:"; +"screen_welcome_title" = "Welkom bij %1$@!"; +"session_verification_banner_message" = "Het lijkt erop dat je een nieuw apparaat gebruikt. Verifieer met een ander apparaat om toegang te krijgen tot je versleutelde berichten."; +"session_verification_banner_title" = "Verifieer dat jij het bent"; +"settings_rageshake" = "Schudden uit woede"; +"settings_rageshake_detection_threshold" = "Drempel voor detectie"; +"settings_version_number" = "Versie: %1$@ (%2$@)"; +"state_event_avatar_changed_too" = "(afbeelding is ook gewijzigd)"; +"state_event_avatar_url_changed" = "%1$@ wijzigde van afbeelding"; +"state_event_avatar_url_changed_by_you" = "Je hebt je afbeelding gewijzigd"; +"state_event_demoted_to_member" = "%1$@ werd gedegradeerd tot lid"; +"state_event_demoted_to_moderator" = "%1$@ werd gedegradeerd tot moderator"; +"state_event_display_name_changed_from" = "%1$@ heeft de weergavenaam aangepast van %2$@ naar %3$@"; +"state_event_display_name_changed_from_by_you" = "Je hebt je weergavenaam aangepast van %1$@ naar %2$@"; +"state_event_display_name_removed" = "%1$@ heeft de weergavenaam verwijderd (dit was %2$@)"; +"state_event_display_name_removed_by_you" = "Je hebt je weergavenaam verwijderd (dit was %1$@)"; +"state_event_display_name_set" = "%1$@ heeft de weergavenaam %2$@ aangenomen"; +"state_event_display_name_set_by_you" = "Je hebt de weergavenaam %1$@ aangenomen"; +"state_event_promoted_to_administrator" = "%1$@ werd bevorderd tot beheerder"; +"state_event_promoted_to_moderator" = "%1$@ werd bevorderd tot moderator"; +"state_event_room_avatar_changed" = "%1$@ heeft de kamerafbeelding gewijzigd"; +"state_event_room_avatar_changed_by_you" = "Je hebt de kamerafbeelding gewijzigd"; +"state_event_room_avatar_removed" = "%1$@ heeft de kamerafbeelding verwijderd"; +"state_event_room_avatar_removed_by_you" = "Je hebt de kamerafbeelding verwijderd"; +"state_event_room_ban" = "%1$@ heeft %2$@ verbannen"; +"state_event_room_ban_by_you" = "Je hebt %1$@ verbannen"; +"state_event_room_created" = "%1$@ heeft de kamer gemaakt"; +"state_event_room_created_by_you" = "Je hebt de kamer gemaakt"; +"state_event_room_invite" = "%1$@ heeft %2$@ uitgenodigd"; +"state_event_room_invite_accepted" = "%1$@ heeft de uitnodiging geaccepteerd"; +"state_event_room_invite_accepted_by_you" = "Je hebt de uitnodiging geaccepteerd"; +"state_event_room_invite_by_you" = "Jij hebt %1$@ uitgenodigd"; +"state_event_room_invite_you" = "%1$@ heeft je uitgenodigd"; +"state_event_room_join" = "%1$@ is tot de kamer toegetreden"; +"state_event_room_join_by_you" = "Je bent toegetreden tot de kamer"; +"state_event_room_knock" = "%1$@ heeft gevraagd om toe te treden"; +"state_event_room_knock_accepted" = "%1$@ heeft %2$@ toegestaan toe te treden"; +"state_event_room_knock_accepted_by_you" = "Je hebt %1$@ toegestaan toe te treden"; +"state_event_room_knock_by_you" = "Je hebt gevraagd om toe te treden"; +"state_event_room_knock_denied" = "%1$@ heeft %2$@'s verzoek om toe te treden afgewezen"; +"state_event_room_knock_denied_by_you" = "Je hebt %1$@'s verzoek om toe te treden afgewezen"; +"state_event_room_knock_denied_you" = "%1$@ heeft je verzoek om toe te treden afgewezen"; +"state_event_room_knock_retracted" = "%1$@ wil niet meer toetreden"; +"state_event_room_knock_retracted_by_you" = "Je hebt je verzoek om toe te treden geannuleerd"; +"state_event_room_leave" = "%1$@ verliet de kamer"; +"state_event_room_leave_by_you" = "Je hebt de kamer verlaten"; +"state_event_room_name_changed" = "%1$@ heeft de kamernaam gewijzigd naar: %2$@"; +"state_event_room_name_changed_by_you" = "Je hebt de kamernaam gewijzigd naar: %1$@"; +"state_event_room_name_removed" = "%1$@ heeft de kamernaam verwijderd"; +"state_event_room_name_removed_by_you" = "Je hebt de kamernaam verwijderd"; +"state_event_room_none" = "%1$@ heeft geen wijzigingen aangebracht"; +"state_event_room_none_by_you" = "Je hebt geen wijzigingen aangebracht"; +"state_event_room_pinned_events_changed" = "%1$@ changed the pinned messages"; +"state_event_room_pinned_events_changed_by_you" = "You changed the pinned messages"; +"state_event_room_pinned_events_pinned" = "%1$@ pinned a message"; +"state_event_room_pinned_events_pinned_by_you" = "You pinned a message"; +"state_event_room_pinned_events_unpinned" = "%1$@ unpinned a message"; +"state_event_room_pinned_events_unpinned_by_you" = "You unpinned a message"; +"state_event_room_reject" = "%1$@ heeft de uitnodiging afgewezen"; +"state_event_room_reject_by_you" = "Je hebt de uitnodiging afgewezen"; +"state_event_room_remove" = "%1$@ heeft %2$@ verwijderd"; +"state_event_room_remove_by_you" = "Je hebt %1$@ verwijderd"; +"state_event_room_third_party_invite" = "%1$@ heeft %2$@ in deze kamer uitgenodigd"; +"state_event_room_third_party_invite_by_you" = "Je hebt %1$@ in deze kamer uitgenodigd"; +"state_event_room_third_party_revoked_invite" = "%1$@ heeft de uitnodiging aan %2$@ om toe te treden tot de kamer ingetrokken"; +"state_event_room_third_party_revoked_invite_by_you" = "Je hebt de uitnodiging aan %1$@ om toe te treden tot de kamer ingetrokken"; +"state_event_room_topic_changed" = "%1$@ heeft het onderwerp gewijzigd naar: %2$@"; +"state_event_room_topic_changed_by_you" = "Je hebt het onderwerp gewijzigd naar: %1$@"; +"state_event_room_topic_removed" = "%1$@ heeft het kameronderwerp verwijderd"; +"state_event_room_topic_removed_by_you" = "Je hebt het kamerondewerp verwijderd"; +"state_event_room_unban" = "%1$@ heeft %2$@ ontbannen"; +"state_event_room_unban_by_you" = "Jij hebt %1$@ ontbannen"; +"state_event_room_unknown_membership_change" = "%1$@ heeft een onbekende lidmaatschapswijziging"; +"test_language_identifier" = "en"; +"test_untranslated_default_language_identifier" = "en"; +"troubleshoot_notifications_entry_point_section" = "Problemen oplossen"; +"troubleshoot_notifications_entry_point_title" = "Problemen met meldingen oplossen"; +"troubleshoot_notifications_screen_action" = "Tests uitvoeren"; +"troubleshoot_notifications_screen_action_again" = "Tests opnieuw uitvoeren"; +"troubleshoot_notifications_screen_failure" = "Sommige tests zijn mislukt. Controleer de details."; +"troubleshoot_notifications_screen_notice" = "Voer de tests uit om problemen in je configuratie op te sporen waardoor meldingen mogelijk niet naar verwachting werken."; +"troubleshoot_notifications_screen_quick_fix_action" = "Probeer het op te lossen"; +"troubleshoot_notifications_screen_success" = "Alle tests zijn geslaagd."; +"troubleshoot_notifications_screen_title" = "Problemen met meldingen oplossen"; +"troubleshoot_notifications_screen_waiting" = "Sommige tests vereisen je aandacht. Controleer de details."; +"troubleshoot_notifications_test_check_permission_description" = "Controleren of de applicatie meldingen kan weergeven."; +"troubleshoot_notifications_test_check_permission_title" = "Controleer machtigingen"; +"troubleshoot_notifications_test_current_push_provider_description" = "Naam van de huidige provider aan het ophalen."; +"troubleshoot_notifications_test_current_push_provider_failure" = "Er zijn geen push-providers geselecteerd."; +"troubleshoot_notifications_test_current_push_provider_success" = "Huidige push-provider: %1$@."; +"troubleshoot_notifications_test_current_push_provider_title" = "Huidige push-provider"; +"troubleshoot_notifications_test_detect_push_provider_description" = "Zorg ervoor dat de applicatie minimaal รฉรฉn push-provider heeft."; +"troubleshoot_notifications_test_detect_push_provider_failure" = "Geen push-providers gevonden."; +"troubleshoot_notifications_test_detect_push_provider_title" = "Push-providers detecteren"; +"troubleshoot_notifications_test_display_notification_description" = "Controleer of de applicatie een melding kan weergeven."; +"troubleshoot_notifications_test_display_notification_failure" = "Er is niet op de melding geklikt."; +"troubleshoot_notifications_test_display_notification_permission_failure" = "Kan de melding niet weergeven."; +"troubleshoot_notifications_test_display_notification_success" = "Er is op de melding geklikt!"; +"troubleshoot_notifications_test_display_notification_title" = "Melding weergeven"; +"troubleshoot_notifications_test_display_notification_waiting" = "Klik op de melding om verder te gaan met de test."; +"troubleshoot_notifications_test_firebase_availability_description" = "Zorg ervoor dat Firebase beschikbaar is."; +"troubleshoot_notifications_test_firebase_availability_failure" = "Firebase is niet beschikbaar."; +"troubleshoot_notifications_test_firebase_availability_success" = "Firebase is beschikbaar."; +"troubleshoot_notifications_test_firebase_availability_title" = "Firebase controleren"; +"troubleshoot_notifications_test_firebase_token_description" = "Zorg ervoor dat de Firebase-token beschikbaar is."; +"troubleshoot_notifications_test_firebase_token_failure" = "Firebase-token is niet bekend."; +"troubleshoot_notifications_test_firebase_token_success" = "Firebase-token: %1$@."; +"troubleshoot_notifications_test_firebase_token_title" = "Firebase-token controleren"; +"troubleshoot_notifications_test_push_loop_back_description" = "Ervoor zorgen dat de applicatie pushberichten ontvangt."; +"troubleshoot_notifications_test_push_loop_back_failure_1" = "Fout: pusher heeft het verzoek afgewezen."; +"troubleshoot_notifications_test_push_loop_back_failure_2" = "Fout: %1$@."; +"troubleshoot_notifications_test_push_loop_back_failure_3" = "Fout, kan push niet testen."; +"troubleshoot_notifications_test_push_loop_back_failure_4" = "Fout, time-out tijdens het wachten op push."; +"troubleshoot_notifications_test_push_loop_back_success" = "Push terugkoppeling duurde %1$d ms."; +"troubleshoot_notifications_test_push_loop_back_title" = "Test Push terugkoppeling"; +"troubleshoot_notifications_test_unified_push_description" = "Ervoor zorgen dat UnifiedPush verdelers beschikbaar zijn."; +"troubleshoot_notifications_test_unified_push_failure" = "Geen push-verdelers gevonden."; +"troubleshoot_notifications_test_unified_push_title" = "UnifiedPush controleren"; +"dialog_title_error" = "Fout"; +"dialog_title_success" = "Geslaagd"; +"notification_fallback_content" = "Melding"; +"notification_invitation_action_join" = "Deelnemen"; +"notification_room_action_mark_as_read" = "Markeren als gelezen"; +"notification_room_action_quick_reply" = "Snel antwoord"; +"screen_room_mentions_at_room_title" = "Iedereen"; +"screen_account_provider_signin_subtitle" = "Dit is waar je gesprekken zullen worden bewaard โ€” net zoals je een e-mailprovider zou gebruiken om je e-mails te bewaren."; +"screen_account_provider_signup_subtitle" = "Dit is waar je gesprekken zullen worden bewaard โ€” net zoals je een e-mailprovider zou gebruiken om je e-mails te bewaren."; +"screen_analytics_settings_help_us_improve" = "Deel anonieme gebruiksgegevens om ons te helpen problemen te identificeren."; +"screen_analytics_settings_read_terms" = "Je kunt al onze voorwaarden %1$@ lezen."; +"screen_analytics_settings_read_terms_content_link" = "hier"; +"screen_blocked_users_unblock_alert_action" = "Deblokkeren"; +"screen_blocked_users_unblock_alert_description" = "Je zult alle berichten van hen weer kunnen zien."; +"screen_blocked_users_unblock_alert_title" = "Gebruiker deblokkeren"; +"screen_bug_report_rash_logs_alert_title" = "%1$@ crashte de laatste keer dat het werd gebruikt. Wil je een crashrapport met ons delen?"; +"screen_create_room_add_people_title" = "Mensen uitnodigen"; +"screen_create_room_room_name_label" = "Naam van de kamer"; +"screen_create_room_title" = "Creรซer een kamer"; +"screen_dm_details_block_alert_action" = "Blokkeren"; +"screen_dm_details_block_alert_description" = "Geblokkeerde gebruikers kunnen je geen berichten sturen en al hun berichten worden verborgen. Je kunt ze op elk moment deblokkeren."; +"screen_dm_details_block_user" = "Gebruiker blokkeren"; +"screen_dm_details_unblock_alert_action" = "Deblokkeren"; +"screen_dm_details_unblock_alert_description" = "Je zult alle berichten van hen weer kunnen zien."; +"screen_dm_details_unblock_user" = "Gebruiker deblokkeren"; +"screen_edit_poll_delete_confirmation_title" = "Peiling verwijderen"; +"screen_edit_poll_title" = "Peiling wijzigen"; +"screen_identity_use_another_device" = "Use another device"; +"screen_login_subtitle" = "Matrix is een open netwerk voor veilige, gedecentraliseerde communicatie."; +"screen_qr_code_login_invalid_scan_state_retry_button" = "Probeer het opnieuw"; +"screen_report_content_block_user" = "Gebruiker blokkeren"; +"screen_room_attachment_source_camera_photo" = "Foto maken"; +"screen_room_change_permissions_everyone" = "Iedereen"; +"screen_room_change_permissions_member_moderation" = "Moderatie van leden"; +"screen_room_change_permissions_messages_and_content" = "Berichten en inhoud"; +"screen_room_change_permissions_room_details" = "Kamergegevens"; +"screen_room_change_role_section_administrators" = "Beheerders"; +"screen_room_change_role_section_moderators" = "Moderators"; +"screen_room_change_role_section_users" = "Leden"; +"screen_room_details_invite_people_title" = "Mensen uitnodigen"; +"screen_room_details_leave_conversation_title" = "Gesprek verlaten"; +"screen_room_details_leave_room_title" = "Ruimte verlaten"; +"screen_room_details_roles_and_permissions" = "Rollen en rechten"; +"screen_room_details_room_name_label" = "Naam van de kamer"; +"screen_room_details_security_title" = "Beveiliging"; +"screen_room_details_topic_title" = "Onderwerp"; +"screen_room_error_failed_processing_media" = "Het verwerken van media voor uploaden is mislukt. Probeer het opnieuw."; +"screen_room_notification_settings_mode_mentions_and_keywords" = "Alleen vermeldingen en trefwoorden"; +"screen_roomlist_filter_people" = "Personen"; +"screen_signout_confirmation_dialog_submit" = "Uitloggen"; +"screen_signout_confirmation_dialog_title" = "Uitloggen"; +"screen_signout_preference_item" = "Uitloggen"; diff --git a/ElementX/Resources/Localizations/nl.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/nl.lproj/Localizable.stringsdict new file mode 100644 index 0000000000..d02360d9f9 --- /dev/null +++ b/ElementX/Resources/Localizations/nl.lproj/Localizable.stringsdict @@ -0,0 +1,326 @@ + + + + + a11y_digits_entered + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d cijfer ingevoerd + other + %1$d cijfers ingevoerd + + + a11y_read_receipts_multiple_with_others + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + Gelezen door %1$@ en %2$d andere + other + Gelezen door %1$@ en %2$d anderen + + + common_member_count + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d lid + other + %1$d leden + + + common_poll_votes_count + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d stem + other + %d stemmen + + + notification_compat_summary_line_for_room + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@: %2$d bericht + other + %1$@: %2$d berichten + + + notification_compat_summary_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d melding + other + %d meldingen + + + notification_invitations + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d uitnodiging + other + %d uitnodigingen + + + notification_new_messages_for_room + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d nieuw bericht + other + %d nieuwe berichten + + + notification_unread_notified_messages + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d ongelezen bericht met melding + other + %d ongelezen berichten met melding + + + notification_unread_notified_messages_in_room_rooms + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d kamer + other + %d kamers + + + screen_app_lock_subtitle + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + Je hebt %1$d poging om te ontgrendelen + other + Je hebt %1$d pogingen om te ontgrendelen + + + screen_app_lock_subtitle_wrong_pin + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + Verkeerde pincode. Je hebt nog %1$d kans + other + Verkeerde pincode. Je hebt nog %1$d kansen + + + 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 persoon + other + %1$d personen + + + screen_room_timeline_state_changes + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d kamerverandering + other + %1$d kamerveranderingen + + + screen_room_typing_many_members + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@, %2$@ en %3$d andere + other + %1$@, %2$@ en %3$d anderen + + + screen_room_typing_many_members_second_component_ios + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d andere + other + %d anderen + + + screen_room_typing_notification + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ is aan het typen + other + %1$@ zijn aan het typen + + + troubleshoot_notifications_test_detect_push_provider_success + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d push-provider gevonden: %2$@ + other + %1$d push-providers gevonden: %2$@ + + + troubleshoot_notifications_test_unified_push_success + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d verdeler gevonden: %2$@. + other + %1$d verdelers gevonden: %2$@. + + + + \ No newline at end of file diff --git a/ElementX/Resources/Localizations/nl.lproj/SAS.strings b/ElementX/Resources/Localizations/nl.lproj/SAS.strings new file mode 100644 index 0000000000..58e130b042 --- /dev/null +++ b/ElementX/Resources/Localizations/nl.lproj/SAS.strings @@ -0,0 +1,64 @@ +"aeroplane" = "Vliegtuig"; +"anchor" = "Anker"; +"apple" = "Appel"; +"ball" = "Bal"; +"banana" = "Banaan"; +"bell" = "Bel"; +"bicycle" = "Fiets"; +"book" = "Boek"; +"butterfly" = "Vlinder"; +"cactus" = "Cactus"; +"cake" = "Taart"; +"cat" = "Kat"; +"clock" = "Wekker"; +"cloud" = "Wolk"; +"corn" = "Maรฏs"; +"dog" = "Hond"; +"elephant" = "Olifant"; +"fire" = "Vuur"; +"fish" = "Vis"; +"flag" = "Vlag"; +"flower" = "Bloem"; +"folder" = "Map"; +"gift" = "Geschenk"; +"glasses" = "Bril"; +"globe" = "Wereldbol"; +"guitar" = "Gitaar"; +"hammer" = "Hamer"; +"hat" = "Hoed"; +"headphones" = "Koptelefoon"; +"heart" = "Hart"; +"horse" = "Paard"; +"hourglass" = "Zandloper"; +"key" = "Sleutel"; +"light_bulb" = "Gloeilamp"; +"lion" = "Leeuw"; +"lock" = "Slot"; +"moon" = "Maan"; +"mushroom" = "Paddenstoel"; +"octopus" = "Octopus"; +"panda" = "Panda"; +"paperclip" = "Papierklemmetje"; +"pencil" = "Potlood"; +"penguin" = "Pinguรฏn"; +"pig" = "Varken"; +"pin" = "Duimspijker"; +"pizza" = "Pizza"; +"rabbit" = "Konijn"; +"robot" = "Robot"; +"rocket" = "Raket"; +"rooster" = "Haan"; +"santa" = "Kerstman"; +"scissors" = "Schaar"; +"smiley" = "Smiley"; +"spanner" = "Moersleutel"; +"strawberry" = "Aardbei"; +"telephone" = "Telefoon"; +"thumbs_up" = "Duim omhoog"; +"train" = "Trein"; +"tree" = "Boom"; +"trophy" = "Trofee"; +"trumpet" = "Trompet"; +"turtle" = "Schildpad"; +"umbrella" = "Paraplu"; +"unicorn" = "Eenhoorn"; \ No newline at end of file diff --git a/ElementX/Resources/Localizations/pl.lproj/Localizable.strings b/ElementX/Resources/Localizations/pl.lproj/Localizable.strings index 735b361def..1c594d2565 100644 --- a/ElementX/Resources/Localizations/pl.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/pl.lproj/Localizable.strings @@ -27,17 +27,20 @@ "action_back" = "Wrรณฤ‡"; "action_call" = "Zadzwoล„"; "action_cancel" = "Anuluj"; +"action_cancel_for_now" = "Cancel for now"; "action_choose_photo" = "Wybierz zdjฤ™cie"; "action_clear" = "Wyczyล›ฤ‡"; "action_close" = "Zamknij"; "action_complete_verification" = "Dokoล„cz weryfikacjฤ™"; "action_confirm" = "Potwierdลบ"; +"action_confirm_password" = "Confirm password"; "action_continue" = "Kontynuuj"; "action_copy" = "Kopiuj"; "action_copy_link" = "Kopiuj link"; "action_copy_link_to_message" = "Kopiuj link do wiadomoล›ci"; "action_create" = "Utwรณrz"; "action_create_a_room" = "Utwรณrz pokรณj"; +"action_deactivate" = "Deactivate"; "action_decline" = "Odrzuฤ‡"; "action_delete_poll" = "Usuล„ ankietฤ™"; "action_disable" = "Wyล‚ฤ…cz"; @@ -49,7 +52,7 @@ "action_end_poll" = "Zakoล„cz ankietฤ™"; "action_enter_pin" = "Wprowadลบ PIN"; "action_forgot_password" = "Nie pamiฤ™tasz hasล‚a?"; -"action_forward" = "Dalej"; +"action_forward" = "Przekaลผ dalej"; "action_go_back" = "Wrรณฤ‡"; "action_invite" = "Zaproล›"; "action_invite_friends" = "Zaproล› znajomych"; @@ -70,6 +73,7 @@ "action_ok" = "Ok"; "action_open_settings" = "Ustawienia"; "action_open_with" = "Otwรณrz za pomocฤ…"; +"action_pin" = "Przypnij"; "action_quick_reply" = "Szybka odpowiedลบ"; "action_quote" = "Cytuj"; "action_react" = "Dodaj reakcjฤ™"; @@ -80,6 +84,7 @@ "action_report_bug" = "Zgล‚oล› bล‚ฤ…d"; "action_report_content" = "Zgล‚oล› treล›ฤ‡"; "action_reset" = "Resetuj"; +"action_reset_identity" = "Zresetuj toลผsamoล›ฤ‡"; "action_retry" = "Sprรณbuj ponownie"; "action_retry_decryption" = "Ponรณw prรณbฤ™ odszyfrowania"; "action_save" = "Zapisz"; @@ -89,8 +94,8 @@ "action_share" = "Udostฤ™pnij"; "action_share_link" = "Udostฤ™pnij link"; "action_sign_in_again" = "Zaloguj siฤ™ ponownie"; -"action_signout" = "Wyloguj siฤ™"; -"action_signout_anyway" = "Wyloguj siฤ™ mimo to"; +"action_signout" = "Wyloguj"; +"action_signout_anyway" = "Wyloguj mimo to"; "action_skip" = "Pomiล„"; "action_start" = "Rozpocznij"; "action_start_chat" = "Rozpocznij chat"; @@ -99,10 +104,18 @@ "action_take_photo" = "Zrรณb zdjฤ™cie"; "action_tap_for_options" = "Stuknij, by wyล›wietliฤ‡ opcje"; "action_try_again" = "Sprรณbuj ponownie"; +"action_unpin" = "Odepnij"; +"action_view_in_timeline" = "View in timeline"; "action_view_source" = "Wyล›wietl ลบrรณdล‚o"; "action_yes" = "Tak"; "action.load_more" = "Zaล‚aduj wiฤ™cej"; -"action.pin" = "Pin"; +"action_deactivate_account" = "Deactivate account"; +"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" = "Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices."; +"banner.set_up_recovery.title" = "Set up recovery"; "common_about" = "O programie"; "common_acceptable_use_policy" = "Polityka uลผytkowania"; "common_advanced_settings" = "Ustawienia zaawansowane"; @@ -114,7 +127,7 @@ "common_call_invite" = "Rozmowa w trakcie (niewspierane)"; "common_call_started" = "Rozpoczฤ™to rozmowฤ™"; "common_chat_backup" = "Backup czatu"; -"common_copyright" = "Copyright"; +"common_copyright" = "Prawa autorskie"; "common_creating_room" = "Tworzenie pokoju..."; "common_current_user_left_room" = "Opuล›ciล‚ pokรณj"; "common_dark" = "Ciemny"; @@ -214,6 +227,7 @@ "common_waiting_for_decryption_key" = "Oczekiwanie na tฤ™ wiadomoล›ฤ‡"; "common.do_not_show_this_again" = "Nie pokazuj ponownie"; "common.open_source_licenses" = "Licencje open-source"; +"common.pinned" = "Pinned"; "common.send_to" = "Wyล›lij do"; "common_no_room_name" = "Brak nazwy pokoju"; "common_poll_end_confirmation" = "Jesteล› pewien, ลผe chcesz zakoล„czyฤ‡ tฤ™ ankietฤ™?"; @@ -222,7 +236,7 @@ "common_unable_to_decrypt_no_access" = "Nie masz uprawnieล„ do tej wiadomoล›ci"; "common_verify_device" = "Weryfikuj urzฤ…dzenie"; "confirm_recovery_key_banner_message" = "Twoja kopia zapasowa czatu jest obecnie niezsynchronizowana. Aby zachowaฤ‡ dostฤ™p do kopii zapasowej czatu, musisz potwierdziฤ‡ klucz odzyskiwania."; -"confirm_recovery_key_banner_title" = "Potwierdลบ klucz odzyskiwania"; +"confirm_recovery_key_banner_title" = "Wprowadลบ swรณj klucz przywracania"; "crash_detection_dialog_content" = "%1$@ ulegล‚ awarii podczas ostatniego uลผycia. Czy chcesz przesล‚aฤ‡ nam raport o awarii?"; "dialog_permission_camera" = "Aby umoลผliwiฤ‡ aplikacji korzystanie z aparatu, prosimy o udzielenie zezwolenia w ustawieniach systemowych."; "dialog_permission_generic" = "Proszฤ™ nadaฤ‡ uprawnienia w ustawieniach systemowych."; @@ -244,6 +258,7 @@ "emoji_picker_category_people" = "Buลบki i osoby"; "emoji_picker_category_places" = "Podrรณลผ i miejsca"; "emoji_picker_category_symbols" = "Symbole"; +"error_account_creation_not_possible" = "Your homeserver needs to be upgraded to support Matrix Authentication Service and account creation."; "error_failed_creating_the_permalink" = "Nie udaล‚o siฤ™ utworzyฤ‡ linku bezpoล›redniego"; "error_failed_loading_map" = "%1$@ nie mogล‚o wczytaฤ‡ mapy. Sprรณbuj ponownie pรณลบniej."; "error_failed_loading_messages" = "Nie udaล‚o siฤ™ zaล‚adowaฤ‡ wiadomoล›ci"; @@ -253,10 +268,12 @@ "error_no_compatible_app_found" = "Nie znaleziono kompatybilnej aplikacji do obsล‚ugi tej akcji."; "error_some_messages_have_not_been_sent" = "Niektรณre wiadomoล›ci nie zostaล‚y wysล‚ane"; "error_unknown" = "Przepraszamy, wystฤ…piล‚ bล‚ฤ…d"; -"event_shield_reason_authenticity_not_guaranteed" = "The authenticity of this encrypted message can't be guaranteed on this device."; -"event_shield_reason_unknown_device" = "Encrypted by an unknown or deleted device."; -"event_shield_reason_unsigned_device" = "Encrypted by a device not verified by its owner."; -"event_shield_reason_unverified_identity" = "Encrypted by an unverified user."; +"event_shield_reason_authenticity_not_guaranteed" = "Autentycznoล›ฤ‡ tej wiadomoล›ci szyfrowanej nie jest gwarantowana na tym urzฤ…dzeniu."; +"event_shield_reason_previously_verified" = "Encrypted by a previously-verified user."; +"event_shield_reason_sent_in_clear" = "Not encrypted."; +"event_shield_reason_unknown_device" = "Zaszyfrowana przez nieznane lub usuniฤ™te urzฤ…dzenie."; +"event_shield_reason_unsigned_device" = "Zaszyfrowana przez urzฤ…dzenie niezweryfikowane przez jego wล‚aล›ciciela."; +"event_shield_reason_unverified_identity" = "Zaszyfrowana przez niezweryfikowanego uลผytkownika."; "full_screen_intent_banner_message" = "Upewnij siฤ™, ลผe nie pominiesz ลผadnego poล‚ฤ…czenia. Zmieล„ swoje ustawienia i zezwรณl na powiadomienia na blokadzie ekranu."; "full_screen_intent_banner_title" = "Popraw jakoล›ฤ‡ swoich rozmรณw"; "invite_friends_rich_title" = "๐Ÿ”๏ธ Doล‚ฤ…cz do mnie na %1$@"; @@ -275,18 +292,21 @@ "notification_inline_reply_failed" = "** Nie udaล‚o siฤ™ wysล‚aฤ‡ - proszฤ™ otworzyฤ‡ pokรณj"; "notification_invitation_action_reject" = "Odrzuฤ‡"; "notification_invite_body" = "Zaprosiล‚(a) ciฤ™ do czatu"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "notification_mentioned_you_body" = "Wspomniano o Tobie: %1$@"; "notification_new_messages" = "Nowe wiadomoล›ci"; "notification_reaction_body" = "Zareagowaล‚ z %1$@"; "notification_room_invite_body" = "Zaprosiล‚ Ciฤ™ do doล‚ฤ…czenia do pokoju"; +"notification_room_invite_body_with_sender" = "%1$@ invited you to join the room"; "notification_sender_me" = "Ja"; +"notification_sender_mention_reply" = "%1$@ mentioned or replied"; "notification_test_push_notification_content" = "Wyล›wietlasz powiadomienie! Kliknij mnie!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; "notification_unread_notified_messages_and_invitation" = "%1$@ i %2$@"; "notification_unread_notified_messages_in_room" = "%1$@ w %2$@"; "notification_unread_notified_messages_in_room_and_invitation" = "%1$@ w %2$@ i %3$@"; -"preference_rageshake" = "Gniewne wstrzฤ…sanie, aby zgล‚osiฤ‡ bล‚ฤ…d"; +"preference_rageshake" = "Wstrzฤ…ล›nij gniewnie, aby zgล‚osiฤ‡ bล‚ฤ…d"; "rageshake_detection_dialog_content" = "Wyglฤ…da na to, ลผe potrzฤ…sasz telefonem z frustracji. Czy chcesz otworzyฤ‡ ekran zgล‚aszania bล‚ฤ™dรณw?"; "rich_text_editor_bullet_list" = "Przeล‚ฤ…cz listฤ™ punktowฤ…"; "rich_text_editor_close_formatting_options" = "Zamknij opcje formatowania"; @@ -294,14 +314,14 @@ "rich_text_editor_composer_placeholder" = "Wiadomoล›ฤ‡..."; "rich_text_editor_create_link" = "Utwรณrz link"; "rich_text_editor_edit_link" = "Edytuj link"; -"rich_text_editor_format_bold" = "Zastosuj pogrubiony format"; -"rich_text_editor_format_italic" = "Zastosuj format kursywy"; -"rich_text_editor_format_strikethrough" = "Zastosuj format przekreล›lenia"; -"rich_text_editor_format_underline" = "Zastosuj format podkreล›lenia"; -"rich_text_editor_full_screen_toggle" = "Przeล‚ฤ…cz tryb peล‚noekranowy"; +"rich_text_editor_format_bold" = "Zastosuj pogrubienie"; +"rich_text_editor_format_italic" = "Zastosuj kursywฤ™"; +"rich_text_editor_format_strikethrough" = "Zastosuj przekreล›lenie"; +"rich_text_editor_format_underline" = "Zastosuj podkreล›lenie"; +"rich_text_editor_full_screen_toggle" = "Przeล‚ฤ…cz peล‚ny ekran"; "rich_text_editor_indent" = "Wciฤ™cie"; -"rich_text_editor_inline_code" = "Zastosuj format kodu wbudowanego"; -"rich_text_editor_link" = "Wstaw ล‚ฤ…cze"; +"rich_text_editor_inline_code" = "Zastosuj formatowanie kodu w wierszu"; +"rich_text_editor_link" = "Wstaw link"; "rich_text_editor_numbered_list" = "Przeล‚ฤ…cz listฤ™ numerowanฤ…"; "rich_text_editor_open_compose_options" = "Otwรณrz opcje tworzenia"; "rich_text_editor_quote" = "Przeล‚ฤ…cz cytat"; @@ -312,31 +332,48 @@ "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_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_pinned_timeline_screen_title_empty" = "Pinned messages"; +"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" = "Powiadom caล‚y pokรณj"; -"screen.room.pinned_banner_indicator" = "%1$@ of %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ Pinned messages"; -"screen.room.pinned_banner_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" = "Loading messageโ€ฆ"; +"screen_room_pinned_banner_view_all_button_title" = "Wyล›wietl wszystkie"; +"screen_room_details_pinned_events_row_title" = "Pinned messages"; +"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_account_provider_change" = "Zmieล„ dostawcฤ™ konta"; "screen_account_provider_form_hint" = "Adres serwera domowego"; "screen_account_provider_form_notice" = "Wprowadลบ wyszukiwane hasล‚o lub adres domeny."; "screen_account_provider_form_subtitle" = "Szukaj serwera firmowego, spoล‚ecznoล›ci lub prywatnego."; "screen_account_provider_form_title" = "Znajdลบ dostawcฤ™ konta"; -"screen_account_provider_signin_title" = "Zamierzasz siฤ™ zalogowaฤ‡ %@"; +"screen_account_provider_signin_title" = "Zamierzasz zalogowaฤ‡ siฤ™ do %@"; "screen_account_provider_signup_title" = "Zamierzasz zaล‚oลผyฤ‡ konto na %@"; -"screen_advanced_settings_developer_mode" = "Tryb dewelopera"; +"screen_advanced_settings_developer_mode" = "Tryb programisty"; "screen_advanced_settings_developer_mode_description" = "Wล‚ฤ…cz, aby uzyskaฤ‡ dostฤ™p do funkcji dla deweloperรณw."; "screen_advanced_settings_rich_text_editor_description" = "Wyล‚ฤ…cz edytor tekstu bogatego, aby pisaฤ‡ tekst Markdown rฤ™cznie."; -"screen_advanced_settings_send_read_receipts" = "Read receipts"; -"screen_advanced_settings_send_read_receipts_description" = "If turned off, your read receipts won't be sent to anyone. You will still receive read receipts from other users."; -"screen_advanced_settings_share_presence" = "Share presence"; -"screen_advanced_settings_share_presence_description" = "If turned off, you wonโ€™t be able to send or receive read receipts or typing notifications."; +"screen_advanced_settings_send_read_receipts" = "Potwierdzenia odczytania"; +"screen_advanced_settings_send_read_receipts_description" = "Gdy wyล‚ฤ…czona, Twoje potwierdzenia odczytania nie zostanฤ… wysล‚ane. Potwierdzenia od innych wciฤ…ลผ bฤ™dฤ… odbierane."; +"screen_advanced_settings_share_presence" = "Udostฤ™pnij obecnoล›ฤ‡"; +"screen_advanced_settings_share_presence_description" = "Gdy wyล‚ฤ…czona, nie bฤ™dziesz mรณgล‚ wysyล‚aฤ‡ lub odbieraฤ‡ potwierdzeล„ odczytu ani powiadomieล„ pisania."; "screen_advanced_settings_view_source_description" = "Wล‚ฤ…cz opcjฤ™, aby wyล›wietliฤ‡ ลบrรณdล‚o wiadomoล›ci na osi czasu."; "screen_analytics_prompt_data_usage" = "Nie bฤ™dziemy rejestrowaฤ‡ ani profilowaฤ‡ ลผadnych danych osobistych"; -"screen_analytics_prompt_help_us_improve" = "Udostฤ™pniaj anonimowe dane dotyczฤ…ce uลผytkowania, aby pomรณc nam identyfikowaฤ‡ problemy."; -"screen_analytics_prompt_read_terms" = "Moลผesz przeczytaฤ‡ wszystkie nasze warunki %1$@."; +"screen_analytics_prompt_help_us_improve" = "Udostฤ™pniaj anonimowe dane uลผytkowania, aby pomรณc nam identyfikowaฤ‡ problemy."; +"screen_analytics_prompt_read_terms" = "Przeczytaj nasze warunki uลผytkowania %1$@."; "screen_analytics_prompt_read_terms_content_link" = "tutaj"; "screen_analytics_prompt_settings" = "Moลผesz to wyล‚ฤ…czyฤ‡ w dowolnym momencie"; -"screen_analytics_prompt_third_party_sharing" = "Nie bฤ™dziemy udostฤ™pniaฤ‡ Twoich danych podmiotom trzecim"; +"screen_analytics_prompt_third_party_sharing" = "Nie bฤ™dziemy udostฤ™pniaฤ‡ Twoich danych stronom trzecim"; "screen_analytics_prompt_title" = "Pomรณลผ nam ulepszyฤ‡ %1$@"; "screen_analytics_settings_share_data" = "Udostฤ™pniaj dane analityczne"; "screen_app_lock_biometric_authentication" = "uwierzytelnienie biometryczne"; @@ -356,23 +393,23 @@ "screen_app_lock_setup_biometric_unlock_subtitle" = "Zaoszczฤ™dลบ sobie trochฤ™ czasu i korzystaj z %1$@ do odblokowywania aplikacji"; "screen_app_lock_setup_choose_pin" = "Wybierz PIN"; "screen_app_lock_setup_confirm_pin" = "Potwierdลบ PIN"; -"screen_app_lock_setup_pin_context" = "Zablokuj %1$@, aby zwiฤ™kszyฤ‡ bezpieczeล„stwo swoich czatรณw.\n\nWybierz coล› ล‚atwego do zapamiฤ™tania. Jeล›li zapomnisz tego PINU, zostaniesz wylogowany z aplikacji."; -"screen_app_lock_setup_pin_forbidden_dialog_content" = "Nie moลผesz wybraฤ‡ tego PINU ze wzglฤ™dรณw bezpieczeล„stwa"; +"screen_app_lock_setup_pin_context" = "Zablokuj %1$@, aby zwiฤ™kszyฤ‡ bezpieczeล„stwo swoich czatรณw.\n\nWybierz coล› ล‚atwego do zapamiฤ™tania. Jeล›li zapomnisz ten PIN, zostaniesz wylogowany z aplikacji."; +"screen_app_lock_setup_pin_forbidden_dialog_content" = "Nie moลผesz wybraฤ‡ tego PIN'u ze wzglฤ™dรณw bezpieczeล„stwa"; "screen_app_lock_setup_pin_forbidden_dialog_title" = "Wybierz inny kod PIN"; "screen_app_lock_setup_pin_mismatch_dialog_content" = "Wprowadลบ ten sam kod PIN dwa razy"; -"screen_app_lock_setup_pin_mismatch_dialog_title" = "PINY nie pasujฤ… do siebie"; +"screen_app_lock_setup_pin_mismatch_dialog_title" = "PIN'y nie pasujฤ… do siebie"; "screen_app_lock_signout_alert_message" = "Aby kontynuowaฤ‡, zaloguj siฤ™ ponownie i utwรณrz nowy kod PIN"; "screen_app_lock_signout_alert_title" = "Trwa wylogowywanie"; -"screen_blocked_users_empty" = "You have no blocked users"; -"screen_blocked_users_unblocking" = "Unblockingโ€ฆ"; -"screen_bug_report_attach_screenshot" = "Doล‚ฤ…cz zrzut ekranu"; -"screen_bug_report_contact_me" = "Moลผecie skontaktowaฤ‡ siฤ™ ze mnฤ…, jeล›li macie jakiekolwiek dodatkowe pytania."; -"screen_bug_report_contact_me_title" = "Napisz do mnie"; +"screen_blocked_users_empty" = "Nie blokujesz ลผadnych uลผytkownikรณw"; +"screen_blocked_users_unblocking" = "Odblokowujฤ™..."; +"screen_bug_report_attach_screenshot" = "Zaล‚ฤ…cz zrzut ekranu"; +"screen_bug_report_contact_me" = "Zezwรณl na kontakt ze mnฤ…, jeล›li sฤ… jakiekolwiek dodatkowe pytania."; +"screen_bug_report_contact_me_title" = "Kontakt ze mnฤ…"; "screen_bug_report_edit_screenshot" = "Edytuj zrzut ekranu"; "screen_bug_report_editor_description" = "Opisz problem. Co zrobiล‚eล›? Czego oczekiwaล‚eล›? Co siฤ™ staล‚o zamiast tego. Podaj jak najwiฤ™cej szczegรณล‚รณw."; "screen_bug_report_editor_placeholder" = "Opisz problem..."; "screen_bug_report_editor_supporting" = "Jeล›li to moลผliwe, napisz zgล‚oszenje w jฤ™zyku angielskim."; -"screen_bug_report_error_description_too_short" = "The description is too short, please provide more details about what happened. Thanks!"; +"screen_bug_report_error_description_too_short" = "Opis jest zbyt krรณtki, podaj wiฤ™cej szczegรณล‚รณw na temat tego co siฤ™ staล‚o. Dziฤ™ki!"; "screen_bug_report_include_crash_logs" = "Wyล›lij logi awarii"; "screen_bug_report_include_logs" = "Zezwรณl na logi"; "screen_bug_report_include_screenshot" = "Wyล›lij zrzut ekranu"; @@ -383,9 +420,9 @@ "screen_change_account_provider_subtitle" = "Uลผyj innego dostawcy konta, takiego jak wล‚asny serwer lub konta sล‚uลผbowego."; "screen_change_account_provider_title" = "Zmieล„ dostawcฤ™ konta"; "screen_change_server_error_invalid_homeserver" = "Nie mogliล›my poล‚ฤ…czyฤ‡ siฤ™ z tym serwerem domowym. Sprawdลบ, czy adres URL serwera zostaล‚ wprowadzony poprawnie. Jeล›li adres URL jest poprawny, skontaktuj siฤ™ z administratorem serwera w celu uzyskania dalszej pomocy."; -"screen_change_server_error_invalid_well_known" = "Sliding sync isn't available due to an issue in the well-known file:\n%1$@"; +"screen_change_server_error_invalid_well_known" = "Sliding sync nie jest dostฤ™pny z powodu problemu w znanym pliku:\n%1$@"; "screen_change_server_error_no_sliding_sync_message" = "Ten serwer obecnie nie obsล‚uguje technologii Sliding Sync."; -"screen_change_server_form_header" = "Adres URL serwera domowego"; +"screen_change_server_form_header" = "URL serwera domowego"; "screen_change_server_form_notice" = "Moลผesz poล‚ฤ…czyฤ‡ siฤ™ tylko z serwerem, ktรณry obsล‚uguje technologiฤ™ Sliding Sync. Administrator serwera domowego bฤ™dzie musiaล‚ jฤ… skonfigurowaฤ‡. %1$@"; "screen_change_server_subtitle" = "Jaki jest adres Twojego serwera?"; "screen_change_server_title" = "Wybierz swรณj serwer"; @@ -395,16 +432,17 @@ "screen_chat_backup_key_backup_title" = "Backup"; "screen_chat_backup_recovery_action_change" = "Zmieล„ klucz przywracania"; "screen_chat_backup_recovery_action_confirm" = "Wprowadลบ klucz przywracania"; -"screen_chat_backup_recovery_action_confirm_description" = "Backup czatu nie jest zsynchronizowany."; +"screen_chat_backup_recovery_action_confirm_description" = "Backup czatu jest niezsynchronizowany."; "screen_chat_backup_recovery_action_setup" = "Skonfiguruj przywracanie"; "screen_chat_backup_recovery_action_setup_description" = "Uzyskaj dostฤ™p do swoich wiadomoล›ci szyfrowanych, jeล›li utracisz wszystkie swoje urzฤ…dzenia lub zostaniesz wylogowany z %1$@."; -"screen_create_new_recovery_key_list_item_1" = "Open %1$@ in a desktop device"; -"screen_create_new_recovery_key_list_item_2" = "Sign into your account again"; -"screen_create_new_recovery_key_list_item_3" = "When asked to verify your device, select %1$@"; -"screen_create_new_recovery_key_list_item_3_reset_all" = "โ€œReset allโ€"; -"screen_create_new_recovery_key_list_item_4" = "Follow the instructions to create a new recovery key"; -"screen_create_new_recovery_key_list_item_5" = "Save your new recovery key in a password manager or encrypted note"; -"screen_create_new_recovery_key_title" = "Reset the encryption for your account using another device"; +"screen_create_account_title" = "Create account"; +"screen_create_new_recovery_key_list_item_1" = "Otwรณrz %1$@ na urzฤ…dzeniu stacjonarnym"; +"screen_create_new_recovery_key_list_item_2" = "Zaloguj siฤ™ ponownie na swoje konto"; +"screen_create_new_recovery_key_list_item_3" = "Gdy pojawi siฤ™ proล›ba o weryfikacjฤ™ urzฤ…dzenia, wybierz %1$@"; +"screen_create_new_recovery_key_list_item_3_reset_all" = "โ€œResetuj wszystkoโ€"; +"screen_create_new_recovery_key_list_item_4" = "Postฤ™puj zgodnie z instrukcjami, aby utworzyฤ‡ nowy klucz przywracania"; +"screen_create_new_recovery_key_list_item_5" = "Zapisz nowy klucz przywracania w menedลผerze haseล‚ lub notatce szyfrowanej"; +"screen_create_new_recovery_key_title" = "Resetuj szyfrowanie swojego konta za pomocฤ… drugiego urzฤ…dzenia"; "screen_create_poll_add_option_btn" = "Dodaj opcjฤ™"; "screen_create_poll_anonymous_desc" = "Pokaลผ wyniki dopiero po zakoล„czeniu ankiety"; "screen_create_poll_anonymous_headline" = "Ukryj gล‚osy"; @@ -415,42 +453,61 @@ "screen_create_poll_question_hint" = "Czego dotyczy ankieta?"; "screen_create_poll_title" = "Utwรณrz ankietฤ™"; "screen_create_room_action_create_room" = "Nowy pokรณj"; -"screen_create_room_error_creating_room" = "Wystฤ…piล‚ bล‚ฤ…d podczas tworzenia pokoju"; +"screen_create_room_error_creating_room" = "Wystฤ…piล‚ bล‚ฤ…d w trakcie tworzenia pokoju"; "screen_create_room_private_option_description" = "Wiadomoล›ci w tym pokoju sฤ… szyfrowane. Szyfrowania nie moลผna pรณลบniej wyล‚ฤ…czyฤ‡."; "screen_create_room_private_option_title" = "Pokรณj prywatny (tylko zaproszenie)"; "screen_create_room_public_option_description" = "Wiadomoล›ci nie sฤ… szyfrowane i kaลผdy moลผe je odczytaฤ‡. Moลผesz aktywowaฤ‡ szyfrowanie pรณลบniej."; -"screen_create_room_public_option_title" = "Pokรณj publiczny (kaลผdy)"; +"screen_create_room_public_option_title" = "Pokรณj publiczny (wszyscy)"; "screen_create_room_topic_label" = "Temat (opcjonalnie)"; +"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_edit_poll_delete_confirmation" = "Czy na pewno chcesz usunฤ…ฤ‡ tฤ™ ankietฤ™?"; "screen_edit_profile_display_name" = "Wyล›wietlana nazwa"; "screen_edit_profile_display_name_placeholder" = "Twoja wyล›wietlana nazwa"; "screen_edit_profile_error" = "Wystฤ…piล‚ nieznany bล‚ฤ…d przez co nie moลผna byล‚o zmieniฤ‡ informacji."; "screen_edit_profile_error_title" = "Nie moลผna zaktualizowaฤ‡ profilu"; "screen_edit_profile_title" = "Edytuj profil"; -"screen_edit_profile_updating_details" = "Aktualizowanie profilu..."; -"screen_identity_confirmation_create_new_recovery_key" = "Create a new recovery key"; -"screen_identity_confirmation_subtitle" = "Verify this device to set up secure messaging."; -"screen_identity_confirmation_title" = "Confirm that it's you"; -"screen_identity_confirmed_subtitle" = "Now you can read or send messages securely, and anyone you chat with can also trust this device."; -"screen_identity_confirmed_title" = "Device verified"; -"screen_identity_use_another_device" = "Use another device"; -"screen_identity_waiting_on_other_device" = "Waiting on other deviceโ€ฆ"; -"screen_invites_decline_chat_message" = "Czy na pewno chcesz odrzuciฤ‡ zaproszenie do doล‚ฤ…czenia do %1$@?"; +"screen_edit_profile_updating_details" = "Aktualizujฤ™ profilโ€ฆ"; +"screen_encryption_reset_action_continue_reset" = "Continue reset"; +"screen_encryption_reset_bullet_1" = "Szczegรณล‚y konta, kontakty, preferencje i lista czatรณw zostanฤ… zachowane"; +"screen_encryption_reset_bullet_2" = "Utracisz istniejฤ…cฤ… historiฤ™ wiadomoล›ci"; +"screen_encryption_reset_bullet_3" = "Wymagana bฤ™dzie ponowna weryfikacja istniejฤ…cych urzฤ…dzeล„ i kontaktรณw"; +"screen_encryption_reset_footer" = "Zresetuj swojฤ… toลผsamoล›ฤ‡ tylko wtedy, gdy nie jesteล› zalogowany na ลผadnym urzฤ…dzeniu i straciล‚eล› swรณj klucz przywracania."; +"screen_encryption_reset_title" = "Zresetuj swojฤ… toลผsamoล›ฤ‡, jeล›li nie moลผesz jej potwierdziฤ‡ w inny sposรณb"; +"screen_identity_confirmation_cannot_confirm" = "Nie moลผesz potwierdziฤ‡?"; +"screen_identity_confirmation_create_new_recovery_key" = "Utwรณrz nowy klucz przywracania"; +"screen_identity_confirmation_subtitle" = "Zweryfikuj to urzฤ…dzenie, aby skonfigurowaฤ‡ bezpieczne przesyล‚anie wiadomoล›ci."; +"screen_identity_confirmation_title" = "Potwierdลบ, ลผe to Ty"; +"screen_identity_confirmation_use_another_device" = "Uลผyj innego urzฤ…dzenia"; +"screen_identity_confirmation_use_recovery_key" = "Uลผyj klucza przywracania"; +"screen_identity_confirmed_subtitle" = "Teraz moลผesz bezpiecznie czytaฤ‡ i wysyล‚aฤ‡ wiadomoล›ci, kaลผdy z kim czatujesz rรณwnieลผ moลผe ufaฤ‡ temu urzฤ…dzeniu."; +"screen_identity_confirmed_title" = "Urzฤ…dzenie zweryfikowane"; +"screen_identity_waiting_on_other_device" = "Oczekiwanie na inne urzฤ…dzenie..."; +"screen_invites_decline_chat_message" = "Czy na pewno chcesz odrzuciฤ‡ zaproszenie doล‚ฤ…czenia do %1$@?"; "screen_invites_decline_chat_title" = "Odrzuฤ‡ zaproszenie"; "screen_invites_decline_direct_chat_message" = "Czy na pewno chcesz odrzuciฤ‡ rozmowฤ™ prywatnฤ… z %1$@?"; "screen_invites_decline_direct_chat_title" = "Odrzuฤ‡ czat"; "screen_invites_empty_list" = "Brak zaproszeล„"; "screen_invites_invited_you" = "%1$@ (%2$@) zaprosiล‚ Ciฤ™"; -"screen_join_room_join_action" = "Join room"; -"screen_join_room_knock_action" = "Knock to join"; -"screen_join_room_space_not_supported_description" = "%1$@ does not support spaces yet. You can access spaces on web."; -"screen_join_room_space_not_supported_title" = "Spaces are not supported yet"; -"screen_join_room_subtitle_knock" = "Click the button below and a room administrator will be notified. Youโ€™ll be able to join the conversation once approved."; -"screen_join_room_subtitle_no_preview" = "You must be a member of this room to view the message history."; -"screen_join_room_title_knock" = "Want to join this room?"; -"screen_join_room_title_no_preview" = "Preview is not available"; +"screen_join_room_join_action" = "Doล‚ฤ…cz do pokoju"; +"screen_join_room_knock_action" = "Zapukaj, by doล‚ฤ…czyฤ‡"; +"screen_join_room_space_not_supported_description" = "%1$@ jeszcze nie obsล‚uguje przestrzeni. Uzyskaj dostฤ™p do przestrzeni w wersji web."; +"screen_join_room_space_not_supported_title" = "Przestrzenie nie sฤ… jeszcze obsล‚ugiwane"; +"screen_join_room_subtitle_knock" = "Kliknij przycisk poniลผej, aby powiadomiฤ‡ administratora pokoju. Po zatwierdzeniu bฤ™dziesz mรณgล‚ doล‚ฤ…czyฤ‡ do rozmowy."; +"screen_join_room_subtitle_no_preview" = "Musisz byฤ‡ czล‚onkiem tego pokoju, aby wyล›wietliฤ‡ historiฤ™ wiadomoล›ci."; +"screen_join_room_title_knock" = "Chcesz doล‚ฤ…czyฤ‡ do tego pokoju?"; +"screen_join_room_title_no_preview" = "Podglฤ…d nie jest dostฤ™pny"; "screen_key_backup_disable_confirmation_action_turn_off" = "Wyล‚ฤ…cz"; -"screen_key_backup_disable_confirmation_description" = "Utracisz dostฤ™p do wiadomoล›ci szyfrowanych, jeล›li zostaniesz wylogowany ze wszystkich urzฤ…dzeล„."; +"screen_key_backup_disable_confirmation_description" = "Jeล›li wylogujesz siฤ™ ze wszystkich urzฤ…dzeล„, stracisz wszystkie wiadomoล›ci szyfrowane."; "screen_key_backup_disable_confirmation_title" = "Czy na pewno chcesz wyล‚ฤ…czyฤ‡ backup?"; "screen_key_backup_disable_description" = "Wyล‚ฤ…czenie backupu spowoduje usuniฤ™cie kopii klucza szyfrowania i wyล‚ฤ…czenie innych funkcji bezpieczeล„stwa. W takim przypadku bฤ™dziesz:"; "screen_key_backup_disable_description_point_1" = "Posiadaล‚ historii wiadomoล›ci szyfrowanych na nowych urzฤ…dzeniach"; @@ -459,7 +516,7 @@ "screen_login_error_deactivated_account" = "To konto zostaล‚o dezaktywowane."; "screen_login_error_invalid_credentials" = "Nieprawidล‚owa nazwa uลผytkownika i/lub hasล‚o"; "screen_login_error_invalid_user_id" = "To nie jest prawidล‚owy identyfikator uลผytkownika. Oczekiwany format: '@user:homeserver.org'"; -"screen_login_error_refresh_tokens" = "This server is configured to use refresh tokens. These aren't supported when using password based login."; +"screen_login_error_refresh_tokens" = "Ten serwer zostaล‚ skonfigurowany do korzystania z tokenรณw odล›wieลผania. Nie sฤ… one obsล‚ugiwane, gdy korzystasz z hasล‚a."; "screen_login_error_unsupported_authentication" = "Wybrany serwer domowy nie obsล‚uguje uwierzytelniania hasล‚em, ani OIDC. Skontaktuj siฤ™ z jego administratorem lub wybierz inny serwer domowy."; "screen_login_form_header" = "Wprowadลบ swoje dane"; "screen_login_title" = "Witaj ponownie!"; @@ -507,58 +564,57 @@ "screen_polls_history_filter_ongoing" = "W trakcie"; "screen_polls_history_filter_past" = "Przeszล‚e"; "screen_polls_history_title" = "Ankiety"; -"screen_qr_code_login_connecting_subtitle" = "Establishing a secure connection"; -"screen_qr_code_login_connection_note_secure_state_description" = "A secure connection could not be made to the new device. Your existing devices are still safe and you don't need to worry about them."; -"screen_qr_code_login_connection_note_secure_state_list_header" = "What now?"; -"screen_qr_code_login_connection_note_secure_state_list_item_1" = "Try signing in again with a QR code in case this was a network problem"; -"screen_qr_code_login_connection_note_secure_state_list_item_2" = "If you encounter the same problem, try a different wifi network or use your mobile data instead of wifi"; -"screen_qr_code_login_connection_note_secure_state_list_item_3" = "If that doesnโ€™t work, sign in manually"; -"screen_qr_code_login_connection_note_secure_state_title" = "Connection not secure"; -"screen_qr_code_login_device_code_subtitle" = "Youโ€™ll be asked to enter the two digits shown on this device."; -"screen_qr_code_login_device_code_title" = "Enter the number below on your other device"; -"screen_qr_code_login_device_not_signed_in_scan_state_description" = "Sign in to your other device and then try again, or use another device thatโ€™s already signed in."; -"screen_qr_code_login_device_not_signed_in_scan_state_subtitle" = "Other device not signed in"; -"screen_qr_code_login_error_cancelled_subtitle" = "The sign in was cancelled on the other device."; -"screen_qr_code_login_error_cancelled_title" = "Sign in request cancelled"; -"screen_qr_code_login_error_declined_subtitle" = "The sign in was declined on the other device."; -"screen_qr_code_login_error_declined_title" = "Sign in declined"; -"screen_qr_code_login_error_expired_subtitle" = "Sign in expired. Please try again."; -"screen_qr_code_login_error_expired_title" = "The sign in was not completed in time"; -"screen_qr_code_login_error_linking_not_suported_subtitle" = "Your other device does not support signing in to %@ with a QR code.\n\nTry signing in manually, or scan the QR code with another device."; -"screen_qr_code_login_error_linking_not_suported_title" = "QR code not supported"; -"screen_qr_code_login_error_sliding_sync_not_supported_subtitle" = "Your account provider does not support %1$@."; -"screen_qr_code_login_error_sliding_sync_not_supported_title" = "%1$@ not supported"; -"screen_qr_code_login_initial_state_button_title" = "Ready to scan"; -"screen_qr_code_login_initial_state_item_1" = "Open %1$@ on a desktop device"; -"screen_qr_code_login_initial_state_item_2" = "Click on your avatar"; -"screen_qr_code_login_initial_state_item_3" = "Select %1$@"; -"screen_qr_code_login_initial_state_item_3_action" = "โ€œLink new deviceโ€"; -"screen_qr_code_login_initial_state_item_4" = "Scan the QR code with this device"; -"screen_qr_code_login_initial_state_title" = "Open %1$@ on another device to get the QR code"; -"screen_qr_code_login_invalid_scan_state_description" = "Use the QR code shown on the other device."; -"screen_qr_code_login_invalid_scan_state_subtitle" = "Wrong QR code"; -"screen_qr_code_login_no_camera_permission_button" = "Go to camera settings"; -"screen_qr_code_login_no_camera_permission_state_description" = "You need to give permission for %1$@ to use your deviceโ€™s camera in order to continue."; -"screen_qr_code_login_no_camera_permission_state_title" = "Allow camera access to scan the QR code"; -"screen_qr_code_login_scanning_state_title" = "Scan the QR code"; -"screen_qr_code_login_start_over_button" = "Start over"; -"screen_qr_code_login_unknown_error_description" = "An unexpected error occurred. Please try again."; -"screen_qr_code_login_verify_code_loading" = "Waiting for your other device"; -"screen_qr_code_login_verify_code_subtitle" = "Your account provider may ask for the following code to verify the sign in."; -"screen_qr_code_login_verify_code_title" = "Your verification code"; +"screen_qr_code_login_connecting_subtitle" = "Nawiฤ…zanie bezpiecznego poล‚ฤ…czenia"; +"screen_qr_code_login_connection_note_secure_state_description" = "Nie udaล‚o siฤ™ nawiฤ…zaฤ‡ bezpiecznego poล‚ฤ…czenia z nowym urzฤ…dzeniem. Twoje istniejฤ…ce urzฤ…dzenia sฤ… nadal bezpieczne i nie musisz siฤ™ o nie martwiฤ‡."; +"screen_qr_code_login_connection_note_secure_state_list_header" = "Co teraz?"; +"screen_qr_code_login_connection_note_secure_state_list_item_1" = "Sprรณbuj zalogowaฤ‡ siฤ™ ponownie za pomocฤ… kodu QR, jeล›li byล‚by to problem z sieciฤ…"; +"screen_qr_code_login_connection_note_secure_state_list_item_2" = "Jeล›li napotkasz ten sam problem, uลผyj innej sieci Wi-FI lub danych mobilnych"; +"screen_qr_code_login_connection_note_secure_state_list_item_3" = "Jeล›li to nie zadziaล‚a, zaloguj siฤ™ rฤ™cznie"; +"screen_qr_code_login_connection_note_secure_state_title" = "Poล‚ฤ…czenie nie jest bezpieczne"; +"screen_qr_code_login_device_code_subtitle" = "Zostaniesz poproszony o wprowadzenie dwรณch cyfr widocznych na tym urzฤ…dzeniu."; +"screen_qr_code_login_device_code_title" = "Wprowadลบ numer poniลผej na innym urzฤ…dzeniu"; +"screen_qr_code_login_device_not_signed_in_scan_state_description" = "Zaloguj siฤ™ na drugie urzฤ…dzenie lub uลผyj tego, ktรณre jest juลผ zalogowane, a nastฤ™pnie sprรณbuj ponownie."; +"screen_qr_code_login_device_not_signed_in_scan_state_subtitle" = "Drugie urzฤ…dzenie nie jest zalogowane"; +"screen_qr_code_login_error_cancelled_subtitle" = "Logowanie zostaล‚o anulowane na drugim urzฤ…dzeniu."; +"screen_qr_code_login_error_cancelled_title" = "Proล›ba o logowanie zostaล‚a anulowana"; +"screen_qr_code_login_error_declined_subtitle" = "Logowanie zostaล‚o odrzucone na drugim urzฤ…dzeniu."; +"screen_qr_code_login_error_declined_title" = "Logowanie odrzucone"; +"screen_qr_code_login_error_expired_subtitle" = "Logowanie wygasล‚o. Sprรณbuj ponownie."; +"screen_qr_code_login_error_expired_title" = "Logowanie nie zostaล‚o ukoล„czone na czas"; +"screen_qr_code_login_error_linking_not_suported_subtitle" = "Twoje drugie urzฤ…dzenie nie wspiera logowania siฤ™ do %@ za pomocฤ… kodu QR.\n\nSprรณbuj zalogowaฤ‡ siฤ™ rฤ™cznie lub zeskanuj kod QR na innym urzฤ…dzeniu."; +"screen_qr_code_login_error_linking_not_suported_title" = "Kod QR nie jest wspierany"; +"screen_qr_code_login_error_sliding_sync_not_supported_subtitle" = "Twรณj dostawca konta nie obsล‚uguje %1$@."; +"screen_qr_code_login_error_sliding_sync_not_supported_title" = "%1$@ nie jest wspierany"; +"screen_qr_code_login_initial_state_button_title" = "Gotowy do skanowania"; +"screen_qr_code_login_initial_state_item_1" = "Otwรณrz %1$@ na urzฤ…dzeniu stacjonarnym"; +"screen_qr_code_login_initial_state_item_2" = "Kliknij na swรณj awatar"; +"screen_qr_code_login_initial_state_item_3" = "Wybierz %1$@"; +"screen_qr_code_login_initial_state_item_3_action" = "โ€œPowiฤ…ลผ nowe urzฤ…dzenieโ€"; +"screen_qr_code_login_initial_state_item_4" = "Zeskanuj kod QR za pomocฤ… tego urzฤ…dzenia"; +"screen_qr_code_login_initial_state_title" = "Otwรณrz %1$@ na innym urzฤ…dzeniu, aby uzyskaฤ‡ kod QR"; +"screen_qr_code_login_invalid_scan_state_description" = "Uลผyj kodu QR widocznego na drugim urzฤ…dzeniu."; +"screen_qr_code_login_invalid_scan_state_subtitle" = "Bล‚ฤ™dny kod QR"; +"screen_qr_code_login_no_camera_permission_button" = "Przejdลบ do ustawieล„ aparatu"; +"screen_qr_code_login_no_camera_permission_state_description" = "Musisz przyznaฤ‡ uprawnienia %1$@ do korzystania z kamery, aby kontynuowaฤ‡."; +"screen_qr_code_login_no_camera_permission_state_title" = "Zezwรณl na dostฤ™p do kamery, aby zeskanowaฤ‡ kod QR"; +"screen_qr_code_login_scanning_state_title" = "Skanuj kod QR"; +"screen_qr_code_login_start_over_button" = "Zacznij od nowa"; +"screen_qr_code_login_unknown_error_description" = "Wystฤ…piล‚ nieoczekiwany bล‚ฤ…d. Sprรณbuj ponownie."; +"screen_qr_code_login_verify_code_loading" = "Oczekiwanie na drugie urzฤ…dzenie"; +"screen_qr_code_login_verify_code_subtitle" = "Twรณj dostawca konta moลผe poprosiฤ‡ o podany kod, aby zweryfikowaฤ‡ logowanie."; +"screen_qr_code_login_verify_code_title" = "Twรณj kod weryfikacyjny"; "screen_recovery_key_change_description" = "Uzyskaj nowy klucz przywracania, jeล›li straciล‚eล› dostฤ™p do obecnego. Po zmianie klucza przywracania stary nie bฤ™dzie juลผ dziaล‚aล‚."; "screen_recovery_key_change_generate_key" = "Generuj nowy klucz przywracania"; "screen_recovery_key_change_generate_key_description" = "Upewnij siฤ™, ลผe klucz przywracania bฤ™dzie trzymany w bezpiecznym miejscu"; "screen_recovery_key_change_success" = "Zmieniono klucz przywracania"; "screen_recovery_key_change_title" = "Zmieniฤ‡ klucz przywracania?"; -"screen_recovery_key_confirm_create_new_recovery_key" = "Create new recovery key"; +"screen_recovery_key_confirm_create_new_recovery_key" = "Utwรณrz nowy klucz przywracania"; "screen_recovery_key_confirm_description" = "Upewnij siฤ™, ลผe nikt nie widzi tego ekranu!"; "screen_recovery_key_confirm_error_content" = "Sprรณbuj ponownie, aby potwierdziฤ‡ dostฤ™p do backupu czatu."; "screen_recovery_key_confirm_error_title" = "Nieprawidล‚owy klucz przywracania"; "screen_recovery_key_confirm_key_description" = "To teลผ zadziaล‚a, jeล›li posiadasz klucz lub frazฤ™ bezpieczeล„stwa."; -"screen_recovery_key_confirm_key_label" = "Recovery key or passcode"; "screen_recovery_key_confirm_key_placeholder" = "Wprowadลบ..."; -"screen_recovery_key_confirm_lost_recovery_key" = "Lost your recovery key?"; +"screen_recovery_key_confirm_lost_recovery_key" = "Zgubiล‚eล› swรณj kod przywracania?"; "screen_recovery_key_confirm_success" = "Potwierdzono klucz przywracania"; "screen_recovery_key_confirm_title" = "Wprowadลบ klucz przywracania"; "screen_recovery_key_copied_to_clipboard" = "Skopiowano klucz przywracania"; @@ -577,7 +633,15 @@ "screen_report_content_block_user_hint" = "Sprawdลบ, czy chcesz ukryฤ‡ wszystkie bieลผฤ…ce i przyszล‚e wiadomoล›ci od tego uลผytkownika."; "screen_report_content_explanation" = "Ta wiadomoล›ฤ‡ zostanie zgล‚oszona do administratora Twojego serwera domowego. Nie bฤ™dzie mรณgล‚ on przeczytaฤ‡ ลผadnych zaszyfrowanych wiadomoล›ci."; "screen_report_content_hint" = "Powรณd zgล‚oszenia treล›ci"; -"screen_room_alias_resolver_resolve_alias_failure" = "Failed to resolve room alias."; +"screen_reset_encryption_confirmation_alert_action" = "Tak, zresetuj teraz"; +"screen_reset_encryption_confirmation_alert_subtitle" = "Tego procesu nie moลผna odwrรณciฤ‡."; +"screen_reset_encryption_confirmation_alert_title" = "Czy na pewno chcesz zresetowaฤ‡ szyfrowanie?"; +"screen_reset_encryption_password_placeholder" = "Wprowadลบ..."; +"screen_reset_encryption_password_subtitle" = "Potwierdลบ, ลผe chcesz zresetowaฤ‡ szyfrowanie."; +"screen_reset_encryption_password_title" = "Wprowadลบ hasล‚o, aby kontynuowaฤ‡"; +"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_room_alias_resolver_resolve_alias_failure" = "Nie udaล‚o siฤ™ uzyskaฤ‡ aliasu pokoju."; "screen_room_attachment_source_camera" = "Kamera"; "screen_room_attachment_source_camera_video" = "Nagraj film"; "screen_room_attachment_source_files" = "Zaล‚ฤ…cznik"; @@ -585,33 +649,33 @@ "screen_room_attachment_source_location" = "Lokalizacja"; "screen_room_attachment_source_poll" = "Ankieta"; "screen_room_attachment_text_formatting" = "Formatowanie tekstu"; -"screen_room_change_permissions_administrators" = "Admins only"; -"screen_room_change_permissions_ban_people" = "Ban people"; -"screen_room_change_permissions_delete_messages" = "Remove messages"; -"screen_room_change_permissions_invite_people" = "Invite people"; -"screen_room_change_permissions_moderators" = "Admins and moderators"; -"screen_room_change_permissions_remove_people" = "Remove people"; -"screen_room_change_permissions_room_avatar" = "Change room avatar"; -"screen_room_change_permissions_room_name" = "Change room name"; -"screen_room_change_permissions_room_topic" = "Change room topic"; -"screen_room_change_permissions_send_messages" = "Send messages"; -"screen_room_change_role_administrators_title" = "Edit Admins"; -"screen_room_change_role_confirm_add_admin_description" = "You will not be able to undo this action. You are promoting the user to have the same power level as you."; -"screen_room_change_role_confirm_add_admin_title" = "Add Admin?"; -"screen_room_change_role_confirm_demote_self_action" = "Demote"; -"screen_room_change_role_confirm_demote_self_description" = "You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the room it will be impossible to regain privileges."; -"screen_room_change_role_confirm_demote_self_title" = "Demote yourself?"; -"screen_room_change_role_invited_member_name" = "%1$@ (Pending)"; -"screen_room_change_role_moderators_admin_section_footer" = "Admins automatically have moderator privileges"; -"screen_room_change_role_moderators_title" = "Edit Moderators"; -"screen_room_change_role_unsaved_changes_description" = "You have unsaved changes."; -"screen_room_change_role_unsaved_changes_title" = "Save changes?"; +"screen_room_change_permissions_administrators" = "Tylko administratorzy"; +"screen_room_change_permissions_ban_people" = "Banowanie osรณb"; +"screen_room_change_permissions_delete_messages" = "Usuwanie wiadomoล›ci"; +"screen_room_change_permissions_invite_people" = "Zapraszanie osรณb"; +"screen_room_change_permissions_moderators" = "Administratorzy i moderatorzy"; +"screen_room_change_permissions_remove_people" = "Usuwanie osรณb"; +"screen_room_change_permissions_room_avatar" = "Zmieล„ awatar pokoju"; +"screen_room_change_permissions_room_name" = "Zmieล„ nazwฤ™ pokoju"; +"screen_room_change_permissions_room_topic" = "Zmieล„ temat pokoju"; +"screen_room_change_permissions_send_messages" = "Wysyล‚anie wiadomoล›ci"; +"screen_room_change_role_administrators_title" = "Edytuj administratorรณw"; +"screen_room_change_role_confirm_add_admin_description" = "Tej akcji nie bฤ™dzie moลผna cofnฤ…ฤ‡. Promujesz uลผytkownika, ktรณry bฤ™dzie posiadaล‚ takie same uprawnienia jak Ty."; +"screen_room_change_role_confirm_add_admin_title" = "Dodaฤ‡ administratora?"; +"screen_room_change_role_confirm_demote_self_action" = "Zdegraduj"; +"screen_room_change_role_confirm_demote_self_description" = "Nie bฤ™dzie moลผna cofnฤ…ฤ‡ tej zmiany, jeล›li siฤ™ zdegradujesz. Jeล›li jesteล› ostatnim uprzywilejowanym uลผytkownikiem w pokoju, nie bฤ™dziesz w stanie odzyskaฤ‡ uprawnieล„."; +"screen_room_change_role_confirm_demote_self_title" = "Zdegradowaฤ‡ siebie?"; +"screen_room_change_role_invited_member_name" = "%1$@ (Oczekujฤ…ce)"; +"screen_room_change_role_moderators_admin_section_footer" = "Administratorzy automatycznie majฤ… uprawnienia moderatora"; +"screen_room_change_role_moderators_title" = "Edytuj moderatorรณw"; +"screen_room_change_role_unsaved_changes_description" = "Masz niezapisane zmiany."; +"screen_room_change_role_unsaved_changes_title" = "Zapisaฤ‡ zmiany?"; "screen_room_details_add_topic_title" = "Dodaj temat"; "screen_room_details_already_a_member" = "Jest juลผ czล‚onkiem"; "screen_room_details_already_invited" = "Juลผ zaproszony"; -"screen_room_details_badge_encrypted" = "Encrypted"; -"screen_room_details_badge_not_encrypted" = "Not encrypted"; -"screen_room_details_badge_public" = "Public room"; +"screen_room_details_badge_encrypted" = "Szyfrowany"; +"screen_room_details_badge_not_encrypted" = "Nieszyfrowany"; +"screen_room_details_badge_public" = "Pokรณj publiczny"; "screen_room_details_edit_room_title" = "Edytuj pokรณj"; "screen_room_details_edition_error" = "Wystฤ…piล‚ nieznany bล‚ฤ…d i nie moลผna byล‚o zmieniฤ‡ informacji."; "screen_room_details_edition_error_title" = "Nie moลผna zaktualizowaฤ‡ pokoju"; @@ -624,10 +688,10 @@ "screen_room_details_notification_mode_default" = "Domyล›lny"; "screen_room_details_notification_title" = "Powiadomienia"; "screen_room_details_share_room_title" = "Udostฤ™pnij pokรณj"; -"screen_room_details_title" = "Room info"; +"screen_room_details_title" = "Informacje pokoju"; "screen_room_details_updating_room" = "Aktualizujฤ™ pokรณjโ€ฆ"; -"screen_room_directory_search_loading_error" = "Failed loading"; -"screen_room_directory_search_title" = "Room directory"; +"screen_room_directory_search_loading_error" = "Bล‚ฤ…d wczytywania"; +"screen_room_directory_search_title" = "Katalog pokoi"; "screen_room_encrypted_history_banner" = "Historia wiadomoล›ci jest obecnie niedostฤ™pna."; "screen_room_encrypted_history_banner_unverified" = "Historia wiadomoล›ci jest niedostฤ™pna w tym pokoju. Zweryfikuj to urzฤ…dzenie, aby zobaczyฤ‡ historiฤ™ wiadomoล›ci."; "screen_room_error_failed_retrieving_user_details" = "Nie moลผna pobraฤ‡ danych uลผytkownika"; @@ -636,32 +700,32 @@ "screen_room_member_details_block_alert_action" = "Zablokuj"; "screen_room_member_details_block_alert_description" = "Zablokowani uลผytkownicy nie bฤ™dฤ… mogli wysyล‚aฤ‡ Ci wiadomoล›ci, a wszystkie ich wiadomoล›ci zostanฤ… ukryte. Moลผesz odblokowaฤ‡ ich w dowolnym momencie."; "screen_room_member_details_block_user" = "Zablokuj uลผytkownika"; -"screen_room_member_details_title" = "Profile"; +"screen_room_member_details_title" = "Profil"; "screen_room_member_details_unblock_alert_action" = "Odblokuj"; "screen_room_member_details_unblock_alert_description" = "Bฤ™dziesz mรณgล‚ ponownie zobaczyฤ‡ wszystkie wiadomoล›ci od tego uลผytkownika."; "screen_room_member_details_unblock_user" = "Odblokuj uลผytkownika"; -"screen_room_member_list_ban_member_confirmation_action" = "Ban"; -"screen_room_member_list_ban_member_confirmation_description" = "They wonโ€™t be able to join this room again if invited."; -"screen_room_member_list_ban_member_confirmation_title" = "Are you sure you want to ban this member?"; -"screen_room_member_list_banned_empty" = "There are no banned users in this room."; -"screen_room_member_list_banning_user" = "Banning %1$@"; -"screen_room_member_list_manage_member_ban" = "Remove and ban member"; -"screen_room_member_list_manage_member_remove" = "Remove from room"; -"screen_room_member_list_manage_member_remove_confirmation_ban" = "Remove and ban member"; -"screen_room_member_list_manage_member_remove_confirmation_kick" = "Only remove member"; -"screen_room_member_list_manage_member_remove_confirmation_title" = "Remove member and ban from joining in the future?"; -"screen_room_member_list_manage_member_unban_action" = "Unban"; -"screen_room_member_list_manage_member_unban_message" = "They will be able to join this room again if invited."; -"screen_room_member_list_manage_member_unban_title" = "Unban user"; -"screen_room_member_list_manage_member_user_info" = "View profile"; -"screen_room_member_list_mode_banned" = "Banned"; -"screen_room_member_list_mode_members" = "Members"; +"screen_room_member_list_ban_member_confirmation_action" = "Zbanuj"; +"screen_room_member_list_ban_member_confirmation_description" = "Nie bฤ™dฤ… mogli ponownie doล‚ฤ…czyฤ‡ do tego pokoju, jeล›li zostanฤ… zaproszeni."; +"screen_room_member_list_ban_member_confirmation_title" = "Czy na pewno chcesz zbanowaฤ‡ tego czล‚onka?"; +"screen_room_member_list_banned_empty" = "W tym pokoju nie ma zbanowanych uลผytkownikรณw."; +"screen_room_member_list_banning_user" = "Banowanie %1$@"; +"screen_room_member_list_manage_member_ban" = "Usuล„ i zbanuj czล‚onka"; +"screen_room_member_list_manage_member_remove" = "Usuล„ z pokoju"; +"screen_room_member_list_manage_member_remove_confirmation_ban" = "Usuล„ i zbanuj czล‚onka"; +"screen_room_member_list_manage_member_remove_confirmation_kick" = "Tylko usuล„ czล‚onka"; +"screen_room_member_list_manage_member_remove_confirmation_title" = "Usunฤ…ฤ‡ czล‚onka i zablokowaฤ‡ moลผliwoล›ฤ‡ doล‚ฤ…czenia w przyszล‚oล›ci?"; +"screen_room_member_list_manage_member_unban_action" = "Odbanuj"; +"screen_room_member_list_manage_member_unban_message" = "Bฤ™dฤ… mogli ponownie doล‚ฤ…czyฤ‡ do tego pokoju, jeล›li zostanฤ… zaproszeni."; +"screen_room_member_list_manage_member_unban_title" = "Odbanuj uลผytkownika"; +"screen_room_member_list_manage_member_user_info" = "Wyล›wietl profil"; +"screen_room_member_list_mode_banned" = "Zbanowanych"; +"screen_room_member_list_mode_members" = "Czล‚onkรณw"; "screen_room_member_list_pending_header_title" = "Oczekiwanie"; -"screen_room_member_list_removing_user" = "Removing %1$@โ€ฆ"; -"screen_room_member_list_role_administrator" = "Admin"; +"screen_room_member_list_removing_user" = "Usuwanie %1$@..."; +"screen_room_member_list_role_administrator" = "Administrator"; "screen_room_member_list_role_moderator" = "Moderator"; "screen_room_member_list_room_members_header_title" = "Czล‚onkowie pokoju"; -"screen_room_member_list_unbanning_user" = "Unbanning %1$@"; +"screen_room_member_list_unbanning_user" = "Odbanowanie %1$@"; "screen_room_notification_settings_allow_custom" = "Zezwalaj na ustawienia niestandardowe"; "screen_room_notification_settings_allow_custom_footnote" = "Wล‚ฤ…czenie tej opcji nadpisze ustawienie domyล›lne"; "screen_room_notification_settings_custom_settings_title" = "Powiadamiaj mnie o tym czacie przez"; @@ -677,20 +741,20 @@ "screen_room_notification_settings_room_custom_settings_title" = "W tym pokoju, powiadamiaj mnie przez"; "screen_room_retry_send_menu_send_again_action" = "Wyล›lij ponownie"; "screen_room_retry_send_menu_title" = "Nie udaล‚o siฤ™ wysล‚aฤ‡ wiadomoล›ci"; -"screen_room_roles_and_permissions_admins" = "Admins"; -"screen_room_roles_and_permissions_change_my_role" = "Change my role"; -"screen_room_roles_and_permissions_change_role_demote_to_member" = "Demote to member"; -"screen_room_roles_and_permissions_change_role_demote_to_moderator" = "Demote to moderator"; -"screen_room_roles_and_permissions_member_moderation" = "Member moderation"; -"screen_room_roles_and_permissions_messages_and_content" = "Messages and content"; -"screen_room_roles_and_permissions_moderators" = "Moderators"; -"screen_room_roles_and_permissions_permissions_header" = "Permissions"; -"screen_room_roles_and_permissions_reset" = "Reset permissions"; -"screen_room_roles_and_permissions_reset_confirm_description" = "Once you reset permissions, you will lose the current settings."; -"screen_room_roles_and_permissions_reset_confirm_title" = "Reset permissions?"; -"screen_room_roles_and_permissions_roles_header" = "Roles"; -"screen_room_roles_and_permissions_room_details" = "Room details"; -"screen_room_roles_and_permissions_title" = "Roles and permissions"; +"screen_room_roles_and_permissions_admins" = "Administratorzy"; +"screen_room_roles_and_permissions_change_my_role" = "Zmieล„ mojฤ… rolฤ™"; +"screen_room_roles_and_permissions_change_role_demote_to_member" = "Zdegraduj do czล‚onka"; +"screen_room_roles_and_permissions_change_role_demote_to_moderator" = "Zdegraduj do moderatora"; +"screen_room_roles_and_permissions_member_moderation" = "Moderacja czล‚onkรณw"; +"screen_room_roles_and_permissions_messages_and_content" = "Wiadomoล›ci i zawartoล›ฤ‡"; +"screen_room_roles_and_permissions_moderators" = "Moderatorzy"; +"screen_room_roles_and_permissions_permissions_header" = "Uprawnienia"; +"screen_room_roles_and_permissions_reset" = "Resetuj uprawnienia"; +"screen_room_roles_and_permissions_reset_confirm_description" = "Po zresetowaniu uprawnieล„ utracisz bieลผฤ…ce ustawienia."; +"screen_room_roles_and_permissions_reset_confirm_title" = "Zresetowaฤ‡ uprawnienia?"; +"screen_room_roles_and_permissions_roles_header" = "Role"; +"screen_room_roles_and_permissions_room_details" = "Szczegรณล‚y pokoju"; +"screen_room_roles_and_permissions_title" = "Role i uprawnienia"; "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"; @@ -700,32 +764,32 @@ "screen_room_timeline_reactions_show_less" = "Pokaลผ mniej"; "screen_room_timeline_reactions_show_more" = "Pokaลผ wiฤ™cej"; "screen_room_timeline_read_marker_title" = "Nowe"; -"screen_room_title" = "Chat"; -"screen_room_typing_many_members_first_component_ios" = "%1$@, %2$@ and "; -"screen_room_typing_notification_plural_ios" = " are typingโ€ฆ"; -"screen_room_typing_notification_singular_ios" = " is typingโ€ฆ"; -"screen_room_typing_two_members" = "%1$@ and %2$@"; +"screen_room_title" = "Czat"; +"screen_room_typing_many_members_first_component_ios" = "%1$@, %2$@ i "; +"screen_room_typing_notification_plural_ios" = " piszฤ…โ€ฆ"; +"screen_room_typing_notification_singular_ios" = " pisze..."; +"screen_room_typing_two_members" = "%1$@ i %2$@"; "screen_room_voice_message_tooltip" = "Przytrzymaj, aby nagrywaฤ‡"; "screen_roomlist_a11y_create_message" = "Utwรณrz nowฤ… rozmowฤ™ lub pokรณj"; "screen_roomlist_empty_message" = "Wyล›lij komuล› wiadomoล›ฤ‡, aby rozpoczฤ…ฤ‡."; "screen_roomlist_empty_title" = "Brak czatรณw."; -"screen_roomlist_filter_favourites" = "Favourites"; -"screen_roomlist_filter_favourites_empty_state_subtitle" = "You can add a chat to your favourites in the chat settings.\nFor now, you can deselect filters in order to see your other chats"; -"screen_roomlist_filter_favourites_empty_state_title" = "You donโ€™t have favourite chats yet"; -"screen_roomlist_filter_invites" = "Invites"; -"screen_roomlist_filter_invites_empty_state_title" = "You don't have any pending invites."; -"screen_roomlist_filter_low_priority" = "Low Priority"; -"screen_roomlist_filter_mixed_empty_state_subtitle" = "You can deselect filters in order to see your other chats"; -"screen_roomlist_filter_mixed_empty_state_title" = "You donโ€™t have chats for this selection"; -"screen_roomlist_filter_people_empty_state_title" = "You donโ€™t have any DMs yet"; -"screen_roomlist_filter_rooms" = "Rooms"; -"screen_roomlist_filter_rooms_empty_state_title" = "Youโ€™re not in any room yet"; -"screen_roomlist_filter_unreads" = "Unreads"; -"screen_roomlist_filter_unreads_empty_state_title" = "Congrats!\nYou donโ€™t have any unread messages!"; +"screen_roomlist_filter_favourites" = "Ulubione"; +"screen_roomlist_filter_favourites_empty_state_subtitle" = "Moลผesz dodaฤ‡ czat do ulubionych w ustawieniach czatu.\nNa razie moลผesz wyczyล›ciฤ‡ filtry, aby zobaczyฤ‡ pozostaล‚e czaty"; +"screen_roomlist_filter_favourites_empty_state_title" = "Nie masz jeszcze ulubionych czatรณw"; +"screen_roomlist_filter_invites" = "Zaproszenia"; +"screen_roomlist_filter_invites_empty_state_title" = "Nie masz ลผadnych oczekujฤ…cych zaproszeล„."; +"screen_roomlist_filter_low_priority" = "Niski priorytet"; +"screen_roomlist_filter_mixed_empty_state_subtitle" = "Wyczyล›ฤ‡ filtry, aby zobaczyฤ‡ pozostaล‚e czaty"; +"screen_roomlist_filter_mixed_empty_state_title" = "Brak czatรณw dla podanych kryteriรณw"; +"screen_roomlist_filter_people_empty_state_title" = "Nie masz jeszcze ลผadnych PW"; +"screen_roomlist_filter_rooms" = "Pokoje"; +"screen_roomlist_filter_rooms_empty_state_title" = "Nie jesteล› jeszcze w ลผadnym pokoju"; +"screen_roomlist_filter_unreads" = "Nieprzeczytane"; +"screen_roomlist_filter_unreads_empty_state_title" = "Gratulacje!\nNie masz ลผadnych nieprzeczytanych wiadomoล›ci!"; "screen_roomlist_main_space_title" = "Wszystkie czaty"; -"screen_roomlist_mark_as_read" = "Mark as read"; -"screen_roomlist_mark_as_unread" = "Mark as unread"; -"screen_roomlist_room_directory_button_title" = "Browse all rooms"; +"screen_roomlist_mark_as_read" = "Oznacz jako przeczytane"; +"screen_roomlist_mark_as_unread" = "Oznacz jako nieprzeczytane"; +"screen_roomlist_room_directory_button_title" = "Przeglฤ…daj wszystkie pokoje"; "screen_server_confirmation_change_server" = "Zmieล„ dostawcฤ™ konta"; "screen_server_confirmation_message_login_element_dot_io" = "Serwer prywatny dla pracownikรณw Element."; "screen_server_confirmation_message_login_matrix_dot_org" = "Matrix to otwarta sieฤ‡ do bezpiecznej i zdecentralizowanej komunikacji."; @@ -733,12 +797,12 @@ "screen_server_confirmation_title_login" = "Zamierzasz siฤ™ zalogowaฤ‡ do %1$@"; "screen_server_confirmation_title_register" = "Zamierzasz utworzyฤ‡ konto na %1$@"; "screen_session_verification_cancelled_subtitle" = "Coล› tu nie gra. Albo upล‚ynฤ…ล‚ limit czasu, albo ลผฤ…danie zostaล‚o odrzucone."; -"screen_session_verification_compare_emojis_subtitle" = "Upewnij siฤ™, ลผe poniลผsze emotikony pasujฤ… do tych wyล›wietlanych na innej sesji."; +"screen_session_verification_compare_emojis_subtitle" = "Upewnij siฤ™, ลผe emoji poniลผej pasujฤ… do tych pokazanych na innej sesji."; "screen_session_verification_compare_emojis_title" = "Porรณwnaj emotki"; "screen_session_verification_compare_numbers_subtitle" = "Upewnij siฤ™, ลผe liczby poniลผej pasujฤ… do tych wyล›wietlanych na innej sesji."; "screen_session_verification_compare_numbers_title" = "Porรณwnaj liczby"; "screen_session_verification_complete_subtitle" = "Twoja nowa sesja jest teraz zweryfikowana. Ma ona dostฤ™p do Twoich zaszyfrowanych wiadomoล›ci, a inni uลผytkownicy bฤ™dฤ… widzieฤ‡ jฤ… jako zaufanฤ…."; -"screen_session_verification_enter_recovery_key" = "Enter recovery key"; +"screen_session_verification_enter_recovery_key" = "Wprowadลบ klucz przywracania"; "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ฤ™"; @@ -775,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "Czy zapisaล‚eล› swรณj klucz przywracania?"; "screen_start_chat_error_starting_chat" = "Wystฤ…piล‚ bล‚ฤ…d podczas prรณby rozpoczฤ™cia czatu"; "screen_view_location_title" = "Lokalizacja"; -"screen_waitlist_message" = "Obecnie istnieje duลผe zapotrzebowanie na %1$@ na %2$@. Wrรณฤ‡ do aplikacji za kilka dni i sprรณbuj ponownie.\n\nDziฤ™kujemy za Twojฤ… cierpliwoล›ฤ‡!"; -"screen_waitlist_title" = "Juลผ prawie gotowe!"; -"screen_waitlist_title_success" = "Witamy!"; "screen_welcome_bullet_1" = "Poล‚ฤ…czenia, ankiety, wyszukiwanie i inne zostanฤ… dodane pรณลบniej w tym roku."; "screen_welcome_bullet_2" = "Historia wiadomoล›ci dla pokoi szyfrowanych nie jest jeszcze dostฤ™pna."; "screen_welcome_bullet_3" = "Chฤ™tnie poznamy Twojฤ… opiniฤ™. Daj nam znaฤ‡, co myล›lisz na stronie ustawieล„."; @@ -792,16 +853,16 @@ "state_event_avatar_changed_too" = "(zdjฤ™cie profilowe teลผ zostaล‚o zmienione)"; "state_event_avatar_url_changed" = "%1$@ zmieniล‚ swoje zdjฤ™cie profilowe"; "state_event_avatar_url_changed_by_you" = "Zmieniล‚eล› swoje zdjฤ™cie profilowe"; -"state_event_demoted_to_member" = "%1$@ was demoted to member"; -"state_event_demoted_to_moderator" = "%1$@ was demoted to moderator"; +"state_event_demoted_to_member" = "%1$@ zostaล‚ zdegradowany do czล‚onka"; +"state_event_demoted_to_moderator" = "%1$@ zostaล‚ zdegradowany do moderatora"; "state_event_display_name_changed_from" = "%1$@ zmieniล‚ swojฤ… wyล›wietlanฤ… nazwฤ™ z %2$@ na %3$@"; "state_event_display_name_changed_from_by_you" = "Zmieniล‚eล› swojฤ… wyล›wietlanฤ… nazwฤ™ z %1$@ na %2$@"; "state_event_display_name_removed" = "%1$@ usunฤ…ล‚ swojฤ… wyล›wietlanฤ… nazwฤ™ (byo to %2$@)"; "state_event_display_name_removed_by_you" = "Usunฤ…ล‚eล› swojฤ… wyล›wietlanฤ… nazwฤ™ (byล‚o to %1$@)"; "state_event_display_name_set" = "%1$@ ustawiล‚ swojฤ… wyล›wietlanฤ… nazwฤ™ na %2$@"; "state_event_display_name_set_by_you" = "Ustawiล‚eล› swojฤ… wyล›wietlanฤ… nazwฤ™ na %1$@"; -"state_event_promoted_to_administrator" = "%1$@ was promoted to admin"; -"state_event_promoted_to_moderator" = "%1$@ was promoted to moderator"; +"state_event_promoted_to_administrator" = "%1$@ zostaล‚ awansowany na administratora"; +"state_event_promoted_to_moderator" = "%1$@ zostaล‚ awansowany na moderatora"; "state_event_room_avatar_changed" = "%1$@ zmieniล‚ zdjฤ™cie profilowe pokoju"; "state_event_room_avatar_changed_by_you" = "Zmieniล‚eล› zdjฤ™cie profilowe pokoju"; "state_event_room_avatar_removed" = "%1$@ usunฤ…ล‚ zdjฤ™cie profilowe pokoju"; @@ -834,8 +895,14 @@ "state_event_room_name_removed_by_you" = "Usunฤ…ล‚eล› nazwฤ™ pokoju"; "state_event_room_none" = "%1$@ nie wprowadziล‚ ลผadnych zmian"; "state_event_room_none_by_you" = "Nie wprowadzono ลผadnych zmian"; +"state_event_room_pinned_events_changed" = "%1$@ zmieniล‚ przypiฤ™te wiadomoล›ci"; +"state_event_room_pinned_events_changed_by_you" = "Zmieniล‚eล› przypiฤ™te wiadomoล›ci"; +"state_event_room_pinned_events_pinned" = "%1$@ przypiฤ…ล‚ wiadomoล›ฤ‡"; +"state_event_room_pinned_events_pinned_by_you" = "Przypiฤ…ล‚eล› wiadomoล›ฤ‡"; +"state_event_room_pinned_events_unpinned" = "%1$@ odpiฤ…ล‚ wiadomoล›ฤ‡"; +"state_event_room_pinned_events_unpinned_by_you" = "Odpiฤ…ล‚eล› wiadomoล›ฤ‡"; "state_event_room_reject" = "%1$@ odrzuciล‚ zaproszenie"; -"state_event_room_reject_by_you" = "Odrzuciล‚eล›(aล›) zaproszenie"; +"state_event_room_reject_by_you" = "Odrzuciล‚eล› zaproszenie"; "state_event_room_remove" = "%1$@ usunฤ…ล‚ %2$@"; "state_event_room_remove_by_you" = "Usunฤ…ล‚eล› %1$@"; "state_event_room_third_party_invite" = "%1$@ wysล‚aล‚ zaproszenie do %2$@, aby doล‚ฤ…czyล‚ do pokoju"; @@ -851,60 +918,60 @@ "state_event_room_unknown_membership_change" = "%1$@ dokonaล‚ nieznanej zmiany w swoim czล‚onkostwie"; "test_language_identifier" = "pl"; "test_untranslated_default_language_identifier" = "en"; -"troubleshoot_notifications_entry_point_section" = "Troubleshoot"; -"troubleshoot_notifications_entry_point_title" = "Troubleshoot notifications"; -"troubleshoot_notifications_screen_action" = "Run tests"; -"troubleshoot_notifications_screen_action_again" = "Run tests again"; -"troubleshoot_notifications_screen_failure" = "Some tests failed. Please check the details."; -"troubleshoot_notifications_screen_notice" = "Run the tests to detect any issue in your configuration that may make notifications not behave as expected."; -"troubleshoot_notifications_screen_quick_fix_action" = "Attempt to fix"; -"troubleshoot_notifications_screen_success" = "All tests passed successfully."; -"troubleshoot_notifications_screen_title" = "Troubleshoot notifications"; -"troubleshoot_notifications_screen_waiting" = "Some tests require your attention. Please check the details."; -"troubleshoot_notifications_test_check_permission_description" = "Check that the application can show notifications."; -"troubleshoot_notifications_test_check_permission_title" = "Check permissions"; -"troubleshoot_notifications_test_current_push_provider_description" = "Get the name of the current provider."; -"troubleshoot_notifications_test_current_push_provider_failure" = "No push providers selected."; -"troubleshoot_notifications_test_current_push_provider_success" = "Current push provider: %1$@."; -"troubleshoot_notifications_test_current_push_provider_title" = "Current push provider"; -"troubleshoot_notifications_test_detect_push_provider_description" = "Ensure that the application has at least one push provider."; -"troubleshoot_notifications_test_detect_push_provider_failure" = "No push providers found."; -"troubleshoot_notifications_test_detect_push_provider_title" = "Detect push providers"; -"troubleshoot_notifications_test_display_notification_description" = "Check that the application can display notification."; -"troubleshoot_notifications_test_display_notification_failure" = "The notification has not been clicked."; -"troubleshoot_notifications_test_display_notification_permission_failure" = "Cannot display the notification."; -"troubleshoot_notifications_test_display_notification_success" = "The notification has been clicked!"; -"troubleshoot_notifications_test_display_notification_title" = "Display notification"; -"troubleshoot_notifications_test_display_notification_waiting" = "Please click on the notification to continue the test."; -"troubleshoot_notifications_test_firebase_availability_description" = "Ensure that Firebase is available."; -"troubleshoot_notifications_test_firebase_availability_failure" = "Firebase is not available."; -"troubleshoot_notifications_test_firebase_availability_success" = "Firebase is available."; -"troubleshoot_notifications_test_firebase_availability_title" = "Check Firebase"; -"troubleshoot_notifications_test_firebase_token_description" = "Ensure that Firebase token is available."; -"troubleshoot_notifications_test_firebase_token_failure" = "Firebase token is not known."; -"troubleshoot_notifications_test_firebase_token_success" = "Firebase token: %1$@."; -"troubleshoot_notifications_test_firebase_token_title" = "Check Firebase token"; -"troubleshoot_notifications_test_push_loop_back_description" = "Ensure that the application is receiving push."; -"troubleshoot_notifications_test_push_loop_back_failure_1" = "Error: pusher has rejected the request."; -"troubleshoot_notifications_test_push_loop_back_failure_2" = "Error: %1$@."; -"troubleshoot_notifications_test_push_loop_back_failure_3" = "Error, cannot test 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_title" = "Test Push loop back"; -"troubleshoot_notifications_test_unified_push_description" = "Ensure that UnifiedPush distributors are available."; -"troubleshoot_notifications_test_unified_push_failure" = "No push distributors found."; -"troubleshoot_notifications_test_unified_push_title" = "Check UnifiedPush"; +"troubleshoot_notifications_entry_point_section" = "Rozwiฤ…zywanie problemรณw"; +"troubleshoot_notifications_entry_point_title" = "Powiadomienia rozwiฤ…zywania problemรณw"; +"troubleshoot_notifications_screen_action" = "Uruchom testy"; +"troubleshoot_notifications_screen_action_again" = "Uruchom testy ponownie"; +"troubleshoot_notifications_screen_failure" = "Niektรณre testy siฤ™ nie powiodล‚y. Sprawdลบ szczegรณล‚y."; +"troubleshoot_notifications_screen_notice" = "Uruchom testy, aby wykryฤ‡ potencjalne problemy z konfiguracjฤ…, jeล›li powiadomienia nie dziaล‚ajฤ… prawidล‚owo."; +"troubleshoot_notifications_screen_quick_fix_action" = "Sprรณbuj naprawiฤ‡"; +"troubleshoot_notifications_screen_success" = "Wszystkie testy przebiegล‚y pomyล›lnie."; +"troubleshoot_notifications_screen_title" = "Powiadomienia rozwiฤ…zywania problemรณw"; +"troubleshoot_notifications_screen_waiting" = "Niektรณre testy wymagajฤ… Twojej uwagi. Sprawdลบ szczegรณล‚y."; +"troubleshoot_notifications_test_check_permission_description" = "Sprawdลบ, czy aplikacja moลผe wyล›wietlaฤ‡ powiadomienia."; +"troubleshoot_notifications_test_check_permission_title" = "Sprawdลบ uprawnienia"; +"troubleshoot_notifications_test_current_push_provider_description" = "Uzyskaj nazwฤ™ bieลผฤ…cego dostawcy."; +"troubleshoot_notifications_test_current_push_provider_failure" = "Nie wybrano dostawcรณw push."; +"troubleshoot_notifications_test_current_push_provider_success" = "Bieลผฤ…cy dostawca push: %1$@."; +"troubleshoot_notifications_test_current_push_provider_title" = "Bieลผฤ…cy dostawca push"; +"troubleshoot_notifications_test_detect_push_provider_description" = "Upewnij siฤ™, ลผe aplikacja ma co najmniej jednego dostawcฤ™ push."; +"troubleshoot_notifications_test_detect_push_provider_failure" = "Nie znaleziono dostawcรณw push."; +"troubleshoot_notifications_test_detect_push_provider_title" = "Wykryj dostawcรณw powiadomieล„ push"; +"troubleshoot_notifications_test_display_notification_description" = "Sprawdลบ, czy aplikacja moลผe wyล›wietlaฤ‡ powiadomienie."; +"troubleshoot_notifications_test_display_notification_failure" = "Powiadomienie nie zostaล‚o klikniฤ™te."; +"troubleshoot_notifications_test_display_notification_permission_failure" = "Nie moลผna wyล›wietliฤ‡ powiadomienia."; +"troubleshoot_notifications_test_display_notification_success" = "Powiadomienie zostaล‚o klikniฤ™te!"; +"troubleshoot_notifications_test_display_notification_title" = "Wyล›wietl powiadomienie"; +"troubleshoot_notifications_test_display_notification_waiting" = "Kliknij powiadomienie, aby kontynuowaฤ‡ test."; +"troubleshoot_notifications_test_firebase_availability_description" = "Upewnij siฤ™, ลผe Firebase jest dostฤ™pny."; +"troubleshoot_notifications_test_firebase_availability_failure" = "Baza Firebase jest niedostฤ™pna."; +"troubleshoot_notifications_test_firebase_availability_success" = "Baza Firebase jest dostฤ™pna."; +"troubleshoot_notifications_test_firebase_availability_title" = "Sprawdลบ Firebase"; +"troubleshoot_notifications_test_firebase_token_description" = "Upewnij siฤ™, ลผe token Firebase jest dostฤ™pny."; +"troubleshoot_notifications_test_firebase_token_failure" = "Token Firebase nie jest znany."; +"troubleshoot_notifications_test_firebase_token_success" = "Token Firebase: %1$@."; +"troubleshoot_notifications_test_firebase_token_title" = "Sprawdลบ token Firebase"; +"troubleshoot_notifications_test_push_loop_back_description" = "Upewnij siฤ™, ลผe aplikacja otrzymuje powiadomienie push."; +"troubleshoot_notifications_test_push_loop_back_failure_1" = "Bล‚ฤ…d: pusher odrzuciล‚ ลผฤ…danie."; +"troubleshoot_notifications_test_push_loop_back_failure_2" = "Bล‚ฤ…d: %1$@."; +"troubleshoot_notifications_test_push_loop_back_failure_3" = "Bล‚ฤ…d, nie moลผna przetestowaฤ‡ push."; +"troubleshoot_notifications_test_push_loop_back_failure_4" = "Bล‚ฤ…d, upล‚ynฤ…ล‚ limit czasu powiadomienia push."; +"troubleshoot_notifications_test_push_loop_back_success" = "Pฤ™tla powrotna push zajฤ™ล‚a %1$d ms."; +"troubleshoot_notifications_test_push_loop_back_title" = "Przetestuj pฤ™tlฤ™ Push back"; +"troubleshoot_notifications_test_unified_push_description" = "Upewnij siฤ™, ลผe dystrybutorzy UnifiedPush sฤ… dostฤ™pni."; +"troubleshoot_notifications_test_unified_push_failure" = "Nie znaleziono dystrybutorรณw push."; +"troubleshoot_notifications_test_unified_push_title" = "Sprawdลบ UnifiedPush"; "dialog_title_error" = "Bล‚ฤ…d"; "dialog_title_success" = "Sukces"; "notification_fallback_content" = "Powiadomienie"; "notification_invitation_action_join" = "Doล‚ฤ…cz"; -"notification_room_action_mark_as_read" = "Mark as read"; +"notification_room_action_mark_as_read" = "Oznacz jako przeczytane"; "notification_room_action_quick_reply" = "Szybka odpowiedลบ"; "screen_room_mentions_at_room_title" = "Wszyscy"; "screen_account_provider_signin_subtitle" = "Tutaj bฤ™dฤ… przechowywane Twoje konwersacje - w podobnej formie jak wiadomoล›ci widniejฤ… na skrzynce e-mail."; "screen_account_provider_signup_subtitle" = "Tutaj bฤ™dฤ… przechowywane Twoje konwersacje - w podobnej formie jak wiadomoล›ci widniejฤ… na skrzynce e-mail."; -"screen_analytics_settings_help_us_improve" = "Udostฤ™pniaj anonimowe dane dotyczฤ…ce uลผytkowania, aby pomรณc nam identyfikowaฤ‡ problemy."; -"screen_analytics_settings_read_terms" = "Moลผesz przeczytaฤ‡ wszystkie nasze warunki %1$@."; +"screen_analytics_settings_help_us_improve" = "Udostฤ™pniaj anonimowe dane uลผytkowania, aby pomรณc nam identyfikowaฤ‡ problemy."; +"screen_analytics_settings_read_terms" = "Przeczytaj nasze warunki uลผytkowania %1$@."; "screen_analytics_settings_read_terms_content_link" = "tutaj"; "screen_blocked_users_unblock_alert_action" = "Odblokuj"; "screen_blocked_users_unblock_alert_description" = "Bฤ™dziesz mรณgล‚ ponownie zobaczyฤ‡ wszystkie wiadomoล›ci od tego uลผytkownika."; @@ -921,28 +988,28 @@ "screen_dm_details_unblock_user" = "Odblokuj uลผytkownika"; "screen_edit_poll_delete_confirmation_title" = "Usuล„ ankietฤ™"; "screen_edit_poll_title" = "Edytuj ankietฤ™"; +"screen_identity_use_another_device" = "Uลผyj innego urzฤ…dzenia"; "screen_login_subtitle" = "Matrix to otwarta sieฤ‡ do bezpiecznej i zdecentralizowanej komunikacji."; "screen_qr_code_login_invalid_scan_state_retry_button" = "Sprรณbuj ponownie"; "screen_report_content_block_user" = "Zablokuj uลผytkownika"; "screen_room_attachment_source_camera_photo" = "Zrรณb zdjฤ™cie"; "screen_room_change_permissions_everyone" = "Wszyscy"; -"screen_room_change_permissions_member_moderation" = "Member moderation"; -"screen_room_change_permissions_messages_and_content" = "Messages and content"; -"screen_room_change_permissions_room_details" = "Room details"; -"screen_room_change_role_section_administrators" = "Admins"; -"screen_room_change_role_section_moderators" = "Moderators"; -"screen_room_change_role_section_users" = "Members"; +"screen_room_change_permissions_member_moderation" = "Moderacja czล‚onkรณw"; +"screen_room_change_permissions_messages_and_content" = "Wiadomoล›ci i zawartoล›ฤ‡"; +"screen_room_change_permissions_room_details" = "Szczegรณล‚y pokoju"; +"screen_room_change_role_section_administrators" = "Administratorzy"; +"screen_room_change_role_section_moderators" = "Moderatorzy"; +"screen_room_change_role_section_users" = "Czล‚onkรณw"; "screen_room_details_invite_people_title" = "Zaproล› znajomych"; "screen_room_details_leave_conversation_title" = "Opuล›ฤ‡ย rozmowฤ™"; "screen_room_details_leave_room_title" = "Opuล›ฤ‡ pokรณj"; -"screen_room_details_roles_and_permissions" = "Roles and permissions"; +"screen_room_details_roles_and_permissions" = "Role i uprawnienia"; "screen_room_details_room_name_label" = "Nazwa pokoju"; "screen_room_details_security_title" = "Bezpieczeล„stwo"; "screen_room_details_topic_title" = "Temat"; "screen_room_error_failed_processing_media" = "Przetwarzanie multimediรณw do przesล‚ania nie powiodล‚o siฤ™, sprรณbuj ponownie."; "screen_room_notification_settings_mode_mentions_and_keywords" = "Tylko wzmianki i sล‚owa kluczowe"; "screen_roomlist_filter_people" = "Osoby"; -"screen_signout_confirmation_dialog_submit" = "Wyloguj siฤ™"; -"screen_signout_confirmation_dialog_title" = "Wyloguj siฤ™"; -"screen_signout_preference_item" = "Wyloguj siฤ™"; -"screen_waitlist_message_success" = "Witamy w %1$@!"; +"screen_signout_confirmation_dialog_submit" = "Wyloguj"; +"screen_signout_confirmation_dialog_title" = "Wyloguj"; +"screen_signout_preference_item" = "Wyloguj"; diff --git a/ElementX/Resources/Localizations/pl.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/pl.lproj/Localizable.stringsdict index 6a44e184a2..fdf4328867 100644 --- a/ElementX/Resources/Localizations/pl.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/pl.lproj/Localizable.stringsdict @@ -218,6 +218,22 @@ Bล‚ฤ™dny PIN. Pozostaล‚o %1$d prรณb + 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 @@ -249,9 +265,9 @@ one %1$d zmiana pokoju few - %1$d zmian pokoju - many %1$d zmiany pokoju + many + %1$d zmian pokoju screen_room_typing_many_members @@ -265,9 +281,11 @@ NSStringFormatValueTypeKey d one - %1$@, %2$@ and %3$d other - other - %1$@, %2$@ and %3$d others + %1$@, %2$@ i %3$d inny + few + %1$@, %2$@ i %3$d innych + many + %1$@, %2$@ i %3$d innych screen_room_typing_many_members_second_component_ios @@ -281,9 +299,11 @@ NSStringFormatValueTypeKey d one - %d other - other - %d others + %d inny + few + %d innych + many + %d innych screen_room_typing_notification @@ -297,7 +317,7 @@ NSStringFormatValueTypeKey d one - %1$@ piszฤ™ + %1$@ pisze few %1$@ piszฤ… many @@ -315,9 +335,11 @@ NSStringFormatValueTypeKey d one - Found %1$d push provider: %2$@ - other - Found %1$d push providers: %2$@ + Znaleziono %1$d dostawcฤ™ push: %2$@ + few + Znaleziono %1$d dostawcรณw push: %2$@ + many + Znaleziono %1$d dostawcรณw push: %2$@ troubleshoot_notifications_test_unified_push_success @@ -331,9 +353,11 @@ NSStringFormatValueTypeKey d one - %1$d distributor found: %2$@. - other - %1$d distributors found: %2$@. + Znaleziono %1$d dystrybutora: %2$@. + few + Znaleziono %1$d dystrybutorรณw: %2$@. + many + Znaleziono %1$d dystrybutorรณw: %2$@. diff --git a/ElementX/Resources/Localizations/pt-BR.lproj/InfoPlist.strings b/ElementX/Resources/Localizations/pt-BR.lproj/InfoPlist.strings new file mode 100644 index 0000000000..0d868c5ebe --- /dev/null +++ b/ElementX/Resources/Localizations/pt-BR.lproj/InfoPlist.strings @@ -0,0 +1,5 @@ +"NSCameraUsageDescription" = "Parar tirar fotos ou gravar vรญdeos e enviรก-los como mensagem, o Element X precisa de acesso ร  cรขmera."; +"NSFaceIDUsageDescription" = "O Face ID รฉ usado para acessar o aplicativo."; +"NSLocationWhenInUseUsageDescription" = "Permitir acesso ร  localizaรงรฃo para que o Element X possa compartilhar a sua localizaรงรฃo."; +"NSMicrophoneUsageDescription" = "Para gravar e enviar mensagens de aรบdio, o Element X precisa de acesso ao microfone."; +"NSPhotoLibraryUsageDescription" = "Permite salvar fotos e vรญdeos para sua galeria."; diff --git a/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings b/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings index 582067644c..0b4aa301e5 100644 --- a/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings @@ -27,17 +27,20 @@ "action_back" = "Voltar"; "action_call" = "Chamar"; "action_cancel" = "Cancelar"; +"action_cancel_for_now" = "Cancel for now"; "action_choose_photo" = "Escolher foto"; "action_clear" = "Limpar"; "action_close" = "Fechar"; "action_complete_verification" = "Verificaรงรฃo completa"; "action_confirm" = "Confirmar"; +"action_confirm_password" = "Confirm password"; "action_continue" = "Continuar"; "action_copy" = "Copiar"; "action_copy_link" = "Copiar link"; "action_copy_link_to_message" = "Copiar link para a mensagem"; "action_create" = "Criar"; "action_create_a_room" = "Criar uma sala"; +"action_deactivate" = "Deactivate"; "action_decline" = "Recusar"; "action_delete_poll" = "Excluir Enquete"; "action_disable" = "Desabilitar"; @@ -70,6 +73,7 @@ "action_ok" = "OK"; "action_open_settings" = "Configuraรงรตes"; "action_open_with" = "Abrir com"; +"action_pin" = "Fixar"; "action_quick_reply" = "Resposta rรกpida"; "action_quote" = "Citaรงรฃo"; "action_react" = "Reagir"; @@ -80,6 +84,7 @@ "action_report_bug" = "Reportar erro"; "action_report_content" = "Denunciar conteรบdo"; "action_reset" = "Redefinir"; +"action_reset_identity" = "Reset identity"; "action_retry" = "Tentar novamente"; "action_retry_decryption" = "Tente descriptografar novamente"; "action_save" = "Salvar"; @@ -99,10 +104,18 @@ "action_take_photo" = "Tirar foto"; "action_tap_for_options" = "Toque para opรงรตes"; "action_try_again" = "Tente novamente"; +"action_unpin" = "Unpin"; +"action_view_in_timeline" = "View in timeline"; "action_view_source" = "Ver fonte"; "action_yes" = "Sim"; "action.load_more" = "Carregar mais"; -"action.pin" = "Fixar"; +"action_deactivate_account" = "Deactivate account"; +"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" = "Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices."; +"banner.set_up_recovery.title" = "Set up recovery"; "common_about" = "Sobre"; "common_acceptable_use_policy" = "Polรญtica de uso aceitรกvel"; "common_advanced_settings" = "Configuraรงรตes avanรงadas"; @@ -172,7 +185,7 @@ "common_room" = "Sala"; "common_room_name" = "Nome da sala"; "common_room_name_placeholder" = "por exemplo, o nome do seu projeto"; -"common_saved_changes" = "Mudanรงas salvas"; +"common_saved_changes" = "Alteraรงรตes salvas"; "common_saving" = "Salvando"; "common_screen_lock" = "Bloqueio de tela"; "common_search_for_someone" = "Procurar alguรฉm"; @@ -214,6 +227,7 @@ "common_waiting_for_decryption_key" = "Aguardando esta mensagem"; "common.do_not_show_this_again" = "Nรฃo mostrar isto novamente"; "common.open_source_licenses" = "Licenรงas de cรณdigo aberto"; +"common.pinned" = "Pinned"; "common.send_to" = "Enviar para"; "common_no_room_name" = "Sem nome de sala"; "common_poll_end_confirmation" = "Tem certeza de que deseja encerrar esta enquete?"; @@ -227,15 +241,15 @@ "dialog_permission_camera" = "Para permitir que o aplicativo use a cรขmera, conceda a permissรฃo nas configuraรงรตes do sistema."; "dialog_permission_generic" = "Por favor, conceda a permissรฃo nas configuraรงรตes do sistema."; "dialog_permission_location_description_ios" = "Permita o acesso em Configuraรงรตes -> Localizaรงรฃo."; -"dialog_permission_location_title_ios" = "%1$@ does not have access to your location."; +"dialog_permission_location_title_ios" = "%1$@ nรฃo tem acesso ร  sua localizaรงรฃo."; "dialog_permission_microphone" = "Para permitir que o aplicativo use o microfone, conceda a permissรฃo nas configuraรงรตes do sistema."; -"dialog_permission_microphone_description_ios" = "Grant access so you can record and send messages with audio."; -"dialog_permission_microphone_title_ios" = "%1$@ needs permission to access your microphone."; +"dialog_permission_microphone_description_ios" = "Permitir acesso para que vocรช possa gravar e enviar mensagens com รกudio."; +"dialog_permission_microphone_title_ios" = "%1$@ precisa de permissรฃo para acessar seu microfone."; "dialog_permission_notification" = "Para permitir que o aplicativo exiba notificaรงรตes, conceda a permissรฃo nas configuraรงรตes do sistema."; "dialog_title_confirmation" = "Confirmaรงรฃo"; "dialog_title_warning" = "Aviso"; -"dialog_unsaved_changes_description_ios" = "Suas mudanรงas nรฃo serรฃo salvas"; -"dialog_unsaved_changes_title" = "Salvar mudanรงas?"; +"dialog_unsaved_changes_description_ios" = "Suas alteraรงรตes nรฃo serรฃo salvas"; +"dialog_unsaved_changes_title" = "Salvar alteraรงรตes?"; "emoji_picker_category_activity" = "Atividades"; "emoji_picker_category_flags" = "Bandeiras"; "emoji_picker_category_foods" = "Comida & Bebida"; @@ -244,6 +258,7 @@ "emoji_picker_category_people" = "Sorrisos & Pessoas"; "emoji_picker_category_places" = "Viagens & Lugares"; "emoji_picker_category_symbols" = "Sรญmbolos"; +"error_account_creation_not_possible" = "Your homeserver needs to be upgraded to support Matrix Authentication Service and account creation."; "error_failed_creating_the_permalink" = "Falha ao criar o link permanente"; "error_failed_loading_map" = "%1$@ nรฃo conseguiu carregar o mapa. Por favor, tente novamente mais tarde."; "error_failed_loading_messages" = "Falha ao carregar mensagens"; @@ -254,6 +269,8 @@ "error_some_messages_have_not_been_sent" = "Algumas mensagens nรฃo foram enviadas"; "error_unknown" = "Desculpe, ocorreu um erro"; "event_shield_reason_authenticity_not_guaranteed" = "The authenticity of this encrypted message can't be guaranteed on this device."; +"event_shield_reason_previously_verified" = "Encrypted by a previously-verified user."; +"event_shield_reason_sent_in_clear" = "Not encrypted."; "event_shield_reason_unknown_device" = "Criptografada por um dispositivo desconhecido ou apagado."; "event_shield_reason_unsigned_device" = "Criptografado por um dispositivo que nรฃo foi verificado pelo seu dono."; "event_shield_reason_unverified_identity" = "Criptografado por um usuรกrio nรฃo verificado."; @@ -275,11 +292,14 @@ "notification_inline_reply_failed" = "** Falha ao enviar - por favor, abra a sala"; "notification_invitation_action_reject" = "Rejeitar"; "notification_invite_body" = "Convidou vocรช para conversar"; -"notification_mentioned_you_body" = "Mentioned you: %1$@"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; +"notification_mentioned_you_body" = "Mencionou vocรช: %1$@"; "notification_new_messages" = "Novas mensagens"; "notification_reaction_body" = "Reagiu com %1$@"; "notification_room_invite_body" = "Convidou vocรช para entrar na sala"; +"notification_room_invite_body_with_sender" = "%1$@ invited you to join the room"; "notification_sender_me" = "Eu"; +"notification_sender_mention_reply" = "%1$@ mentioned or replied"; "notification_test_push_notification_content" = "Vocรช estรก visualizando a notificaรงรฃo! Clique em mim!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -299,23 +319,40 @@ "rich_text_editor_format_strikethrough" = "Aplicar formato tachado"; "rich_text_editor_format_underline" = "Aplicar sublinhado"; "rich_text_editor_full_screen_toggle" = "Alternar o modo de tela cheia"; -"rich_text_editor_indent" = "Indent"; +"rich_text_editor_indent" = "Identar"; "rich_text_editor_inline_code" = "Aplicar formato de cรณdigo embutido"; "rich_text_editor_link" = "Definir link"; "rich_text_editor_numbered_list" = "Alternar lista numerada"; "rich_text_editor_open_compose_options" = "Abrir opรงรตes de composiรงรฃo"; "rich_text_editor_quote" = "Alternar citaรงรฃo"; "rich_text_editor_remove_link" = "Remover link"; -"rich_text_editor_unindent" = "Unindent"; +"rich_text_editor_unindent" = "Desidentar"; "rich_text_editor_url_placeholder" = "Link"; "rich_text_editor_a11y_add_attachment" = "Adicionar anexo"; "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_room_mentions_at_room_subtitle" = "Notify the whole room"; -"screen.room.pinned_banner_indicator" = "%1$@ of %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ Pinned messages"; -"screen.room.pinned_banner_view_all_button_title" = "View All"; +"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_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_pinned_timeline_screen_title_empty" = "Pinned messages"; +"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" = "Notificar a sala inteira"; +"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_details_pinned_events_row_title" = "Pinned messages"; +"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_account_provider_change" = "Alterar provedor da conta"; "screen_account_provider_form_hint" = "Endereรงo do servidor"; "screen_account_provider_form_notice" = "Insira um termo de pesquisa ou um endereรงo de domรญnio."; @@ -326,11 +363,11 @@ "screen_advanced_settings_developer_mode" = "Modo de desenvolvedor"; "screen_advanced_settings_developer_mode_description" = "Habilite para ter acesso a recursos e funcionalidades para desenvolvedores."; "screen_advanced_settings_rich_text_editor_description" = "Desative o editor de rich text para digitar Markdown manualmente."; -"screen_advanced_settings_send_read_receipts" = "Read receipts"; -"screen_advanced_settings_send_read_receipts_description" = "If turned off, your read receipts won't be sent to anyone. You will still receive read receipts from other users."; -"screen_advanced_settings_share_presence" = "Share presence"; -"screen_advanced_settings_share_presence_description" = "If turned off, you wonโ€™t be able to send or receive read receipts or typing notifications."; -"screen_advanced_settings_view_source_description" = "Enable option to view message source in the timeline."; +"screen_advanced_settings_send_read_receipts" = "Confirmaรงรตes de leitura"; +"screen_advanced_settings_send_read_receipts_description" = "Se desligado, suas confirmaรงรตes de leitura nรฃo serรฃo enviadas para ninguรฉm. Vocรช ainda receberรก confirmaรงรตes de leitura de outros usuรกrios."; +"screen_advanced_settings_share_presence" = "Compartilhar presenรงa"; +"screen_advanced_settings_share_presence_description" = "Se desligado, vocรช nรฃo poderรก enviar ou receber confirmaรงรตes de leitura ou notificaรงรตes de digitaรงรฃo."; +"screen_advanced_settings_view_source_description" = "Ativar a opรงรฃo de visualizar o fonte da mensagem na linha do tempo."; "screen_analytics_prompt_data_usage" = "Nรฃo registraremos nem criaremos perfil baseado em qualquer dado pessoal"; "screen_analytics_prompt_help_us_improve" = "Compartilhe dados de uso anรดnimos para nos ajudar a identificar problemas."; "screen_analytics_prompt_read_terms" = "Vocรช pode ler todos os nossos termos %1$@ ."; @@ -339,11 +376,11 @@ "screen_analytics_prompt_third_party_sharing" = "Nรฃo compartilharemos seus dados com terceiros"; "screen_analytics_prompt_title" = "Ajude a melhorar o %1$@"; "screen_analytics_settings_share_data" = "Compartilhar dados de utilizaรงรฃo"; -"screen_app_lock_biometric_authentication" = "biometric authentication"; -"screen_app_lock_biometric_unlock" = "biometric unlock"; -"screen_app_lock_biometric_unlock_reason_ios" = "Authentication is needed to access your app"; +"screen_app_lock_biometric_authentication" = "autenticaรงรฃo por biometria"; +"screen_app_lock_biometric_unlock" = "desbloqueio por biometria"; +"screen_app_lock_biometric_unlock_reason_ios" = "A autenticaรงรฃo รฉ necessรกria para acessar o aplicativo"; "screen_app_lock_forgot_pin" = "Esqueceu o PIN?"; -"screen_app_lock_settings_change_pin" = "Mudar cรณdigo de PIN"; +"screen_app_lock_settings_change_pin" = "Alterar cรณdigo de PIN"; "screen_app_lock_settings_enable_biometric_unlock" = "Permitir desbloqueio biomรฉtrico"; "screen_app_lock_settings_enable_face_id_ios" = "Permitir Face ID"; "screen_app_lock_settings_enable_optic_id_ios" = "Permitir ID รณtico"; @@ -351,20 +388,20 @@ "screen_app_lock_settings_remove_pin" = "Remover PIN"; "screen_app_lock_settings_remove_pin_alert_message" = "Tem certeza de que quer remover o PIN?"; "screen_app_lock_settings_remove_pin_alert_title" = "Remover PIN?"; -"screen_app_lock_setup_biometric_unlock_allow_title" = "Allow %1$@"; -"screen_app_lock_setup_biometric_unlock_skip" = "Iโ€™d rather use PIN"; -"screen_app_lock_setup_biometric_unlock_subtitle" = "Save yourself some time and use %1$@ to unlock the app each time"; +"screen_app_lock_setup_biometric_unlock_allow_title" = "Permitir %1$@"; +"screen_app_lock_setup_biometric_unlock_skip" = "Prefiro usar o PIN"; +"screen_app_lock_setup_biometric_unlock_subtitle" = "Poupe tempo e use %1$@ para desbloquear o aplicativo todas as vezes"; "screen_app_lock_setup_choose_pin" = "Escolher PIN"; "screen_app_lock_setup_confirm_pin" = "Confirmar PIN"; -"screen_app_lock_setup_pin_context" = "Lock %1$@ to add extra security to your chats.\n\nChoose something memorable. If you forget this PIN, you will be logged out of the app."; -"screen_app_lock_setup_pin_forbidden_dialog_content" = "You cannot choose this as your PIN code for security reasons"; -"screen_app_lock_setup_pin_forbidden_dialog_title" = "Choose a different PIN"; -"screen_app_lock_setup_pin_mismatch_dialog_content" = "Please enter the same PIN twice"; +"screen_app_lock_setup_pin_context" = "Bloqueie o %1$@ para adicionar uma seguranรงa extra ร s suas conversas.\n\nEscolha algo memorรกvel. Se vocรช esquecer este PIN, vocรช serรก desconectado do app."; +"screen_app_lock_setup_pin_forbidden_dialog_content" = "Vocรช nรฃo pode escolher este PIN por razรตes de seguranรงa"; +"screen_app_lock_setup_pin_forbidden_dialog_title" = "Escolha um PIN diferente"; +"screen_app_lock_setup_pin_mismatch_dialog_content" = "Por favor, insira o mesmo PIN duas vezes"; "screen_app_lock_setup_pin_mismatch_dialog_title" = "Os PINs nรฃo correspondem"; -"screen_app_lock_signout_alert_message" = "Youโ€™ll need to re-login and create a new PIN to proceed"; +"screen_app_lock_signout_alert_message" = "Vocรช terรก que fazer login novamente e criar um novo PIN para prosseguir"; "screen_app_lock_signout_alert_title" = "Vocรช estรก sendo desconectado"; -"screen_blocked_users_empty" = "You have no blocked users"; -"screen_blocked_users_unblocking" = "Unblockingโ€ฆ"; +"screen_blocked_users_empty" = "Vocรช nรฃo tem usuรกrios bloqueados"; +"screen_blocked_users_unblocking" = "Desbloqueando..."; "screen_bug_report_attach_screenshot" = "Anexar captura de tela"; "screen_bug_report_contact_me" = "Vocรช pode entrar em contato comigo se tiver alguma pergunta adicional."; "screen_bug_report_contact_me_title" = "Entre em contato comigo"; @@ -377,7 +414,7 @@ "screen_bug_report_include_logs" = "Permitir registros"; "screen_bug_report_include_screenshot" = "Enviar captura de tela"; "screen_bug_report_logs_description" = "Os registros serรฃo incluรญdos com sua mensagem para garantir que tudo esteja funcionando corretamente. Para enviar sua mensagem sem registros, desative essa configuraรงรฃo."; -"screen_bug_report_view_logs" = "View logs"; +"screen_bug_report_view_logs" = "Ver registros"; "screen_change_account_provider_matrix_org_subtitle" = "O Matrix.org รฉ um grande servidor gratuito na rede pรบblica Matrix para comunicaรงรฃo segura e descentralizada, administrado pela Fundaรงรฃo Matrix.org."; "screen_change_account_provider_other" = "Outro"; "screen_change_account_provider_subtitle" = "Use um provedor de conta diferente, como seu prรณprio servidor privado ou uma conta corporativa."; @@ -393,11 +430,12 @@ "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_recovery_action_change" = "Mudar chave de recuperaรงรฃo"; +"screen_chat_backup_recovery_action_change" = "Alterar chave de recuperaรงรฃo"; "screen_chat_backup_recovery_action_confirm" = "Insira a chave de recuperaรงรฃo"; "screen_chat_backup_recovery_action_confirm_description" = "Seu backup das conversas estรก atualmente fora de sincronia."; "screen_chat_backup_recovery_action_setup" = "Configurar a recuperaรงรฃo"; "screen_chat_backup_recovery_action_setup_description" = "Tenha acesso ร s suas mensagens criptografadas se vocรช perder todos os seus dispositivos ou for desconectado do %1$@ em qualquer lugar."; +"screen_create_account_title" = "Create account"; "screen_create_new_recovery_key_list_item_1" = "Open %1$@ in a desktop device"; "screen_create_new_recovery_key_list_item_2" = "Sign into your account again"; "screen_create_new_recovery_key_list_item_3" = "When asked to verify your device, select %1$@"; @@ -421,19 +459,38 @@ "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_title" = "Sala pรบblica (qualquer pessoa)"; "screen_create_room_topic_label" = "Tรณpico (opcional)"; -"screen_edit_poll_delete_confirmation" = "Are you sure you want to delete this poll?"; +"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_edit_poll_delete_confirmation" = "Tem certeza de que quer deletar esta enquete?"; "screen_edit_profile_display_name" = "Nome de exibiรงรฃo"; "screen_edit_profile_display_name_placeholder" = "Seu nome de exibiรงรฃo"; "screen_edit_profile_error" = "Um erro desconhecido foi encontrado e as informaรงรตes nรฃo puderam ser alteradas."; "screen_edit_profile_error_title" = "Nรฃo foi possรญvel atualizar o perfil"; "screen_edit_profile_title" = "Editar perfil"; "screen_edit_profile_updating_details" = "Atualizando o perfil..."; +"screen_encryption_reset_action_continue_reset" = "Continue reset"; +"screen_encryption_reset_bullet_1" = "Your account details, contacts, preferences, and chat list will be kept"; +"screen_encryption_reset_bullet_2" = "You will lose your existing message history"; +"screen_encryption_reset_bullet_3" = "You will need to verify all your existing devices and contacts again"; +"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_identity_confirmation_create_new_recovery_key" = "Create a new recovery key"; "screen_identity_confirmation_subtitle" = "Verify this device to set up secure messaging."; -"screen_identity_confirmation_title" = "Confirm that it's you"; +"screen_identity_confirmation_title" = "Confirm your identity"; +"screen_identity_confirmation_use_another_device" = "Usar outro dispositivo"; +"screen_identity_confirmation_use_recovery_key" = "Use recovery key"; "screen_identity_confirmed_subtitle" = "Now you can read or send messages securely, and anyone you chat with can also trust this device."; -"screen_identity_confirmed_title" = "Device verified"; -"screen_identity_use_another_device" = "Use another device"; +"screen_identity_confirmed_title" = "Dispositivo verificado"; "screen_identity_waiting_on_other_device" = "Waiting on other deviceโ€ฆ"; "screen_invites_decline_chat_message" = "Tem certeza de que deseja recusar o convite para ingressar em %1$@?"; "screen_invites_decline_chat_title" = "Recusar convite"; @@ -485,14 +542,14 @@ "screen_notification_settings_enable_notifications" = "Ativar notificaรงรตes neste dispositivo"; "screen_notification_settings_failed_fixing_configuration" = "A configuraรงรฃo nรฃo foi corrigida, tente novamente."; "screen_notification_settings_group_chats" = "Bate-papos em grupo"; -"screen_notification_settings_invite_for_me_label" = "Invitations"; +"screen_notification_settings_invite_for_me_label" = "Convites"; "screen_notification_settings_mentions_only_disclaimer" = "Your homeserver does not support this option in encrypted rooms, you may not get notified in some rooms."; "screen_notification_settings_mentions_section_title" = "Menรงรตes"; "screen_notification_settings_mode_all" = "Todos"; "screen_notification_settings_mode_mentions" = "Menรงรตes"; "screen_notification_settings_notification_section_title" = "Me notifique para"; "screen_notification_settings_room_mention_label" = "Notifique-me em @room"; -"screen_notification_settings_system_notifications_action_required" = "To receive notifications, please change your %1$@."; +"screen_notification_settings_system_notifications_action_required" = "Para receber notificaรงรตes, altere seu %1$@."; "screen_notification_settings_system_notifications_action_required_content_link" = "configuraรงรตes do sistema"; "screen_notification_settings_system_notifications_turned_off" = "Notificaรงรตes do sistema desativadas"; "screen_notification_settings_title" = "Notificaรงรตes"; @@ -501,12 +558,12 @@ "screen_onboarding_sign_up" = "Criar conta"; "screen_onboarding_welcome_message" = "Bem-vindo ao mais rรกpido %1$@ de todos os tempos. Turbinado para velocidade e simplicidade."; "screen_onboarding_welcome_subtitle" = "Bem-vindo ao %1$@. Turbinado, para velocidade e simplicidade"; -"screen_onboarding_welcome_title" = "Be in your element"; -"screen_polls_history_empty_ongoing" = "Can't find any ongoing polls."; -"screen_polls_history_empty_past" = "Can't find any past polls."; -"screen_polls_history_filter_ongoing" = "Ongoing"; -"screen_polls_history_filter_past" = "Past"; -"screen_polls_history_title" = "Polls"; +"screen_onboarding_welcome_title" = "Esteja no seu elemento"; +"screen_polls_history_empty_ongoing" = "Nรฃo foi possรญvel encontrar nenhuma enquete em andamento."; +"screen_polls_history_empty_past" = "Nรฃo foi possรญvel encontrar nenhuma enquete anterior."; +"screen_polls_history_filter_ongoing" = "Em andamento"; +"screen_polls_history_filter_past" = "Anteriores"; +"screen_polls_history_title" = "Enquetes"; "screen_qr_code_login_connecting_subtitle" = "Establishing a secure connection"; "screen_qr_code_login_connection_note_secure_state_description" = "A secure connection could not be made to the new device. Your existing devices are still safe and you don't need to worry about them."; "screen_qr_code_login_connection_note_secure_state_list_header" = "What now?"; @@ -554,15 +611,14 @@ "screen_recovery_key_confirm_create_new_recovery_key" = "Create new recovery key"; "screen_recovery_key_confirm_description" = "Certifique-se de que ninguรฉm possa ver essa tela!"; "screen_recovery_key_confirm_error_content" = "Please try again to confirm access to your chat backup."; -"screen_recovery_key_confirm_error_title" = "Incorrect recovery key"; +"screen_recovery_key_confirm_error_title" = "Chave de recuperaรงรฃo incorreta"; "screen_recovery_key_confirm_key_description" = "Se vocรช tiver uma chave de seguranรงa ou frase de seguranรงa, isso tambรฉm funcionarรก."; -"screen_recovery_key_confirm_key_label" = "Recovery key or passcode"; "screen_recovery_key_confirm_key_placeholder" = "Inserir..."; "screen_recovery_key_confirm_lost_recovery_key" = "Lost your recovery key?"; "screen_recovery_key_confirm_success" = "Chave de recuperaรงรฃo confirmada"; "screen_recovery_key_confirm_title" = "Insira sua chave de recuperaรงรฃo"; -"screen_recovery_key_copied_to_clipboard" = "Copied recovery key"; -"screen_recovery_key_generating_key" = "Generatingโ€ฆ"; +"screen_recovery_key_copied_to_clipboard" = "Chave de recuperaรงรฃo copiada"; +"screen_recovery_key_generating_key" = "Gerando..."; "screen_recovery_key_save_action" = "Salvar chave de recuperaรงรฃo"; "screen_recovery_key_save_description" = "Anote sua chave de recuperaรงรฃo em algum lugar seguro ou salve-a em um gerenciador de senhas."; "screen_recovery_key_save_key_description" = "Toque para copiar a chave de recuperaรงรฃo"; @@ -577,6 +633,14 @@ "screen_report_content_block_user_hint" = "Marque se vocรช deseja ocultar todas as mensagens atuais e futuras desse usuรกrio"; "screen_report_content_explanation" = "Essa mensagem serรก reportada ao administrador do seu homeserver. Eles nรฃo conseguirรฃo ler nenhuma mensagem criptografada."; "screen_report_content_hint" = "Motivo para denunciar este conteรบdo"; +"screen_reset_encryption_confirmation_alert_action" = "Yes, reset now"; +"screen_reset_encryption_confirmation_alert_subtitle" = "This process is irreversible."; +"screen_reset_encryption_confirmation_alert_title" = "Are you sure you want to reset your identity?"; +"screen_reset_encryption_password_placeholder" = "Enterโ€ฆ"; +"screen_reset_encryption_password_subtitle" = "Confirm that you want to reset your identity."; +"screen_reset_encryption_password_title" = "Enter your account password to continue"; +"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_room_alias_resolver_resolve_alias_failure" = "Failed to resolve room alias."; "screen_room_attachment_source_camera" = "Cรขmera"; "screen_room_attachment_source_camera_video" = "Gravar vรญdeo"; @@ -585,27 +649,27 @@ "screen_room_attachment_source_location" = "Localizaรงรฃo"; "screen_room_attachment_source_poll" = "Enquete"; "screen_room_attachment_text_formatting" = "Formataรงรฃo de texto"; -"screen_room_change_permissions_administrators" = "Admins only"; -"screen_room_change_permissions_ban_people" = "Ban people"; -"screen_room_change_permissions_delete_messages" = "Remove messages"; -"screen_room_change_permissions_invite_people" = "Invite people"; -"screen_room_change_permissions_moderators" = "Admins and moderators"; -"screen_room_change_permissions_remove_people" = "Remove people"; -"screen_room_change_permissions_room_avatar" = "Change room avatar"; -"screen_room_change_permissions_room_name" = "Change room name"; -"screen_room_change_permissions_room_topic" = "Change room topic"; -"screen_room_change_permissions_send_messages" = "Send messages"; -"screen_room_change_role_administrators_title" = "Edit Admins"; +"screen_room_change_permissions_administrators" = "Somente administradores"; +"screen_room_change_permissions_ban_people" = "Banir pessoas"; +"screen_room_change_permissions_delete_messages" = "Remover mensagens"; +"screen_room_change_permissions_invite_people" = "Convidar pessoas"; +"screen_room_change_permissions_moderators" = "Administradores e moderadores"; +"screen_room_change_permissions_remove_people" = "Remover pessoas"; +"screen_room_change_permissions_room_avatar" = "Alterar avatar da sala"; +"screen_room_change_permissions_room_name" = "Alterar nome da sala"; +"screen_room_change_permissions_room_topic" = "Alterar tรณpico da sala"; +"screen_room_change_permissions_send_messages" = "Enviar mensagens"; +"screen_room_change_role_administrators_title" = "Editar administradores"; "screen_room_change_role_confirm_add_admin_description" = "You will not be able to undo this action. You are promoting the user to have the same power level as you."; -"screen_room_change_role_confirm_add_admin_title" = "Add Admin?"; +"screen_room_change_role_confirm_add_admin_title" = "Adicionar administrador?"; "screen_room_change_role_confirm_demote_self_action" = "Demote"; "screen_room_change_role_confirm_demote_self_description" = "You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the room it will be impossible to regain privileges."; "screen_room_change_role_confirm_demote_self_title" = "Demote yourself?"; "screen_room_change_role_invited_member_name" = "%1$@ (Pending)"; "screen_room_change_role_moderators_admin_section_footer" = "Admins automatically have moderator privileges"; -"screen_room_change_role_moderators_title" = "Edit Moderators"; -"screen_room_change_role_unsaved_changes_description" = "You have unsaved changes."; -"screen_room_change_role_unsaved_changes_title" = "Save changes?"; +"screen_room_change_role_moderators_title" = "Editar moderadores"; +"screen_room_change_role_unsaved_changes_description" = "Vocรช tem alteraรงรตes nรฃo salvas."; +"screen_room_change_role_unsaved_changes_title" = "Salvar alteraรงรตes?"; "screen_room_details_add_topic_title" = "Adicionar tรณpico"; "screen_room_details_already_a_member" = "Jรก รฉ membro"; "screen_room_details_already_invited" = "Jรก foi convidado"; @@ -627,7 +691,7 @@ "screen_room_details_title" = "Room info"; "screen_room_details_updating_room" = "Atualizando a sala..."; "screen_room_directory_search_loading_error" = "Failed loading"; -"screen_room_directory_search_title" = "Room directory"; +"screen_room_directory_search_title" = "Diretรณrio de salas"; "screen_room_encrypted_history_banner" = "O histรณrico de mensagens nรฃo estรก disponรญvel no momento."; "screen_room_encrypted_history_banner_unverified" = "Message history is unavailable in this room. Verify this device to see your message history."; "screen_room_error_failed_retrieving_user_details" = "Nรฃo foi possรญvel recuperar os detalhes do usuรกrio"; @@ -640,28 +704,28 @@ "screen_room_member_details_unblock_alert_action" = "Desbloquear"; "screen_room_member_details_unblock_alert_description" = "Vocรช poderรก ver todas as mensagens deles novamente."; "screen_room_member_details_unblock_user" = "Desbloquear usuรกrio"; -"screen_room_member_list_ban_member_confirmation_action" = "Ban"; +"screen_room_member_list_ban_member_confirmation_action" = "Banir"; "screen_room_member_list_ban_member_confirmation_description" = "They wonโ€™t be able to join this room again if invited."; -"screen_room_member_list_ban_member_confirmation_title" = "Are you sure you want to ban this member?"; +"screen_room_member_list_ban_member_confirmation_title" = "Tem certeza de que quer banir este membro?"; "screen_room_member_list_banned_empty" = "There are no banned users in this room."; -"screen_room_member_list_banning_user" = "Banning %1$@"; -"screen_room_member_list_manage_member_ban" = "Remove and ban member"; -"screen_room_member_list_manage_member_remove" = "Remove from room"; -"screen_room_member_list_manage_member_remove_confirmation_ban" = "Remove and ban member"; -"screen_room_member_list_manage_member_remove_confirmation_kick" = "Only remove member"; -"screen_room_member_list_manage_member_remove_confirmation_title" = "Remove member and ban from joining in the future?"; -"screen_room_member_list_manage_member_unban_action" = "Unban"; +"screen_room_member_list_banning_user" = "Banindo %1$@"; +"screen_room_member_list_manage_member_ban" = "Remover e banir membro"; +"screen_room_member_list_manage_member_remove" = "Remover da sala"; +"screen_room_member_list_manage_member_remove_confirmation_ban" = "Remover e banir membro"; +"screen_room_member_list_manage_member_remove_confirmation_kick" = "Somente remover membro"; +"screen_room_member_list_manage_member_remove_confirmation_title" = "Remover membro e banir de entrar novamente no futuro?"; +"screen_room_member_list_manage_member_unban_action" = "Desbanir"; "screen_room_member_list_manage_member_unban_message" = "They will be able to join this room again if invited."; -"screen_room_member_list_manage_member_unban_title" = "Unban user"; -"screen_room_member_list_manage_member_user_info" = "View profile"; -"screen_room_member_list_mode_banned" = "Banned"; -"screen_room_member_list_mode_members" = "Members"; +"screen_room_member_list_manage_member_unban_title" = "Desbanir usuรกrio"; +"screen_room_member_list_manage_member_user_info" = "Ver perfil"; +"screen_room_member_list_mode_banned" = "Banidos"; +"screen_room_member_list_mode_members" = "Membros"; "screen_room_member_list_pending_header_title" = "Pendente"; -"screen_room_member_list_removing_user" = "Removing %1$@โ€ฆ"; -"screen_room_member_list_role_administrator" = "Admin"; -"screen_room_member_list_role_moderator" = "Moderator"; +"screen_room_member_list_removing_user" = "Removendo %1$@โ€ฆ"; +"screen_room_member_list_role_administrator" = "Administrador"; +"screen_room_member_list_role_moderator" = "Moderador"; "screen_room_member_list_room_members_header_title" = "Membros da sala"; -"screen_room_member_list_unbanning_user" = "Unbanning %1$@"; +"screen_room_member_list_unbanning_user" = "Desbanindo %1$@"; "screen_room_notification_settings_allow_custom" = "Permitir configuraรงรฃo personalizada"; "screen_room_notification_settings_allow_custom_footnote" = "Ativar isso substituirรก sua configuraรงรฃo padrรฃo"; "screen_room_notification_settings_custom_settings_title" = "Me notifique nesta conversa para"; @@ -677,20 +741,20 @@ "screen_room_notification_settings_room_custom_settings_title" = "Nesta sala, notifique-me para"; "screen_room_retry_send_menu_send_again_action" = "Enviar novamente"; "screen_room_retry_send_menu_title" = "Sua mensagem nรฃo foi enviada"; -"screen_room_roles_and_permissions_admins" = "Admins"; -"screen_room_roles_and_permissions_change_my_role" = "Change my role"; +"screen_room_roles_and_permissions_admins" = "Administradores"; +"screen_room_roles_and_permissions_change_my_role" = "Alterar meu cargo"; "screen_room_roles_and_permissions_change_role_demote_to_member" = "Demote to member"; "screen_room_roles_and_permissions_change_role_demote_to_moderator" = "Demote to moderator"; -"screen_room_roles_and_permissions_member_moderation" = "Member moderation"; -"screen_room_roles_and_permissions_messages_and_content" = "Messages and content"; -"screen_room_roles_and_permissions_moderators" = "Moderators"; -"screen_room_roles_and_permissions_permissions_header" = "Permissions"; -"screen_room_roles_and_permissions_reset" = "Reset permissions"; +"screen_room_roles_and_permissions_member_moderation" = "Moderaรงรฃo de membros"; +"screen_room_roles_and_permissions_messages_and_content" = "Mensagens e conteรบdo"; +"screen_room_roles_and_permissions_moderators" = "Moderadores"; +"screen_room_roles_and_permissions_permissions_header" = "Permissรตes"; +"screen_room_roles_and_permissions_reset" = "Redefinir permissรตes"; "screen_room_roles_and_permissions_reset_confirm_description" = "Once you reset permissions, you will lose the current settings."; -"screen_room_roles_and_permissions_reset_confirm_title" = "Reset permissions?"; -"screen_room_roles_and_permissions_roles_header" = "Roles"; -"screen_room_roles_and_permissions_room_details" = "Room details"; -"screen_room_roles_and_permissions_title" = "Roles and permissions"; +"screen_room_roles_and_permissions_reset_confirm_title" = "Redefinir permissรตes?"; +"screen_room_roles_and_permissions_roles_header" = "Cargos"; +"screen_room_roles_and_permissions_room_details" = "Detalhes da sala"; +"screen_room_roles_and_permissions_title" = "Cargos e permissรตes"; "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."; @@ -701,31 +765,31 @@ "screen_room_timeline_reactions_show_more" = "Mostrar mais"; "screen_room_timeline_read_marker_title" = "Novo"; "screen_room_title" = "Chat"; -"screen_room_typing_many_members_first_component_ios" = "%1$@, %2$@ and "; -"screen_room_typing_notification_plural_ios" = " are typingโ€ฆ"; -"screen_room_typing_notification_singular_ios" = " is typingโ€ฆ"; -"screen_room_typing_two_members" = "%1$@ and %2$@"; +"screen_room_typing_many_members_first_component_ios" = "%1$@, %2$@ e "; +"screen_room_typing_notification_plural_ios" = " estรฃo digitandoโ€ฆ"; +"screen_room_typing_notification_singular_ios" = " estรก digitandoโ€ฆ"; +"screen_room_typing_two_members" = "%1$@ e %2$@"; "screen_room_voice_message_tooltip" = "Segure para gravar"; "screen_roomlist_a11y_create_message" = "Criar uma nova conversa ou sala"; "screen_roomlist_empty_message" = "Comece enviando uma mensagem para alguรฉm."; "screen_roomlist_empty_title" = "Ainda nรฃo hรก conversas."; -"screen_roomlist_filter_favourites" = "Favourites"; +"screen_roomlist_filter_favourites" = "Favoritos"; "screen_roomlist_filter_favourites_empty_state_subtitle" = "You can add a chat to your favourites in the chat settings.\nFor now, you can deselect filters in order to see your other chats"; -"screen_roomlist_filter_favourites_empty_state_title" = "You donโ€™t have favourite chats yet"; +"screen_roomlist_filter_favourites_empty_state_title" = "Vocรช nรฃo tem nenhuma conversa favorita ainda"; "screen_roomlist_filter_invites" = "Invites"; "screen_roomlist_filter_invites_empty_state_title" = "You don't have any pending invites."; -"screen_roomlist_filter_low_priority" = "Low Priority"; +"screen_roomlist_filter_low_priority" = "Baixa prioridade"; "screen_roomlist_filter_mixed_empty_state_subtitle" = "You can deselect filters in order to see your other chats"; -"screen_roomlist_filter_mixed_empty_state_title" = "You donโ€™t have chats for this selection"; -"screen_roomlist_filter_people_empty_state_title" = "You donโ€™t have any DMs yet"; -"screen_roomlist_filter_rooms" = "Rooms"; -"screen_roomlist_filter_rooms_empty_state_title" = "Youโ€™re not in any room yet"; -"screen_roomlist_filter_unreads" = "Unreads"; -"screen_roomlist_filter_unreads_empty_state_title" = "Congrats!\nYou donโ€™t have any unread messages!"; +"screen_roomlist_filter_mixed_empty_state_title" = "Vocรช nรฃo tem conversas para esta seleรงรฃo"; +"screen_roomlist_filter_people_empty_state_title" = "Vocรช nรฃo tem nenhum conversa privada ainda"; +"screen_roomlist_filter_rooms" = "Salas"; +"screen_roomlist_filter_rooms_empty_state_title" = "Vocรช nรฃo estรก em nenhuma sala ainda"; +"screen_roomlist_filter_unreads" = "Nรฃo lidos"; +"screen_roomlist_filter_unreads_empty_state_title" = "Parabรฉns!\nVocรช nรฃo tem nenhuma mensagem nรฃo lida!"; "screen_roomlist_main_space_title" = "Conversas"; -"screen_roomlist_mark_as_read" = "Mark as read"; -"screen_roomlist_mark_as_unread" = "Mark as unread"; -"screen_roomlist_room_directory_button_title" = "Browse all rooms"; +"screen_roomlist_mark_as_read" = "Marcar como lido"; +"screen_roomlist_mark_as_unread" = "Marcar como nรฃo lido"; +"screen_roomlist_room_directory_button_title" = "Navegar por todas as salas"; "screen_server_confirmation_change_server" = "Alterar provedor da conta"; "screen_server_confirmation_message_login_element_dot_io" = "Um servidor privado para funcionรกrios do Element."; "screen_server_confirmation_message_login_matrix_dot_org" = "A Matrix รฉ uma rede aberta para comunicaรงรฃo segura e descentralizada."; @@ -735,16 +799,16 @@ "screen_session_verification_cancelled_subtitle" = "Algo nรฃo parece certo. Ou a solicitaรงรฃo atingiu o tempo limite ou a solicitaรงรฃo foi negada."; "screen_session_verification_compare_emojis_subtitle" = "Confirme se os emojis abaixo correspondem aos mostrados em sua outra sessรฃo."; "screen_session_verification_compare_emojis_title" = "Compare os emojis"; -"screen_session_verification_compare_numbers_subtitle" = "Confirm that the numbers below match those shown on your other session."; -"screen_session_verification_compare_numbers_title" = "Compare numbers"; +"screen_session_verification_compare_numbers_subtitle" = "Confirme se os nรบmeros abaixo correspondem aos mostrados em sua outra sessรฃo."; +"screen_session_verification_compare_numbers_title" = "Comparar nรบmeros"; "screen_session_verification_complete_subtitle" = "Sua nova sessรฃo estรก agora verificada. Ela tem acesso ร s suas mensagens criptografadas e outros usuรกrios a verรฃo como confiรกvel."; -"screen_session_verification_enter_recovery_key" = "Enter recovery key"; +"screen_session_verification_enter_recovery_key" = "Insira a chave de recuperaรงรฃo"; "screen_session_verification_open_existing_session_subtitle" = "Prove que รฉ vocรช para acessar seu histรณrico de mensagens criptografadas."; "screen_session_verification_open_existing_session_title" = "Abrir uma sessรฃo existente"; "screen_session_verification_positive_button_canceled" = "Repetir verificaรงรฃo"; "screen_session_verification_positive_button_initial" = "Estou pronto"; "screen_session_verification_positive_button_verifying_ongoing" = "Esperando para combinar"; -"screen_session_verification_ready_subtitle" = "Compare a unique set of emojis."; +"screen_session_verification_ready_subtitle" = "Compare um conjunto รบnico de emojis."; "screen_session_verification_request_accepted_subtitle" = "Compare os emojis รบnicos, garantindo que apareรงam na mesma ordem."; "screen_session_verification_they_dont_match" = "Eles nรฃo combinam"; "screen_session_verification_they_match" = "Eles combinam"; @@ -764,20 +828,17 @@ "screen_signout_confirmation_dialog_content" = "Vocรช tem certeza que deseja sair?"; "screen_signout_in_progress_dialog_content" = "Saindo..."; "screen_signout_key_backup_disabled_subtitle" = "You are about to sign out of your last session. If you sign out now, you will lose access to your encrypted messages."; -"screen_signout_key_backup_disabled_title" = "You have turned off backup"; +"screen_signout_key_backup_disabled_title" = "Vocรช desativou o backup"; "screen_signout_key_backup_offline_subtitle" = "Your keys were still being backed up when you went offline. Reconnect so that your keys can be backed up before signing out."; "screen_signout_key_backup_offline_title" = "Your keys are still being backed up"; "screen_signout_key_backup_ongoing_subtitle" = "Please wait for this to complete before signing out."; -"screen_signout_key_backup_ongoing_title" = "Your keys are still being backed up"; +"screen_signout_key_backup_ongoing_title" = "O backup das suas chaves ainda estรก em andamento"; "screen_signout_recovery_disabled_subtitle" = "You are about to sign out of your last session. If you sign out now, you'll lose access to your encrypted messages."; -"screen_signout_recovery_disabled_title" = "Recovery not set up"; +"screen_signout_recovery_disabled_title" = "A recuperaรงรฃo nรฃo estรก configurada"; "screen_signout_save_recovery_key_subtitle" = "You are about to sign out of your last session. If you sign out now, you might lose access to your encrypted messages."; -"screen_signout_save_recovery_key_title" = "Have you saved your recovery key?"; +"screen_signout_save_recovery_key_title" = "Vocรช salvou sua chave de recuperaรงรฃo?"; "screen_start_chat_error_starting_chat" = "Ocorreu um erro ao tentar iniciar um chat"; "screen_view_location_title" = "Localizaรงรฃo"; -"screen_waitlist_message" = "Hรก uma grande demanda por %1$@ sobre %2$@ no momento. Volte ao aplicativo em alguns dias e tente novamente. \n\nObrigado pela sua paciรชncia!"; -"screen_waitlist_title" = "Vocรช estรก quase lรก."; -"screen_waitlist_title_success" = "Vocรช estรก dentro."; "screen_welcome_bullet_1" = "Chamadas, enquetes, pesquisa e muito mais serรฃo adicionadas ainda este ano."; "screen_welcome_bullet_2" = "O histรณrico de mensagens para salas criptografadas ainda nรฃo estรก disponรญvel."; "screen_welcome_bullet_3" = "Adorarรญamos ouvir sua opiniรฃo. Deixe-nos saber o que vocรช pensa atravรฉs da pรกgina de configuraรงรตes."; @@ -792,16 +853,16 @@ "state_event_avatar_changed_too" = "(o avatar tambรฉm foi alterado)"; "state_event_avatar_url_changed" = "%1$@ mudou seu avatar"; "state_event_avatar_url_changed_by_you" = "Vocรช mudou seu avatar"; -"state_event_demoted_to_member" = "%1$@ was demoted to member"; -"state_event_demoted_to_moderator" = "%1$@ was demoted to moderator"; +"state_event_demoted_to_member" = "%1$@ foi rebaixado a membro"; +"state_event_demoted_to_moderator" = "%1$@ foi rebaixado a moderador"; "state_event_display_name_changed_from" = "%1$@ mudou seu nome de exibiรงรฃo de %2$@ para %3$@"; "state_event_display_name_changed_from_by_you" = "Vocรช alterou seu nome de exibiรงรฃo de %1$@ para %2$@"; "state_event_display_name_removed" = "%1$@ removeu seu nome de exibiรงรฃo (era %2$@)"; "state_event_display_name_removed_by_you" = "Vocรช removeu seu nome de exibiรงรฃo (era %1$@)"; "state_event_display_name_set" = "%1$@ definiu seu nome de exibiรงรฃo como %2$@"; "state_event_display_name_set_by_you" = "Vocรช definiu seu nome de exibiรงรฃo como %1$@"; -"state_event_promoted_to_administrator" = "%1$@ was promoted to admin"; -"state_event_promoted_to_moderator" = "%1$@ was promoted to moderator"; +"state_event_promoted_to_administrator" = "%1$@ foi promovido a administrador"; +"state_event_promoted_to_moderator" = "%1$@ foi promovido a moderador"; "state_event_room_avatar_changed" = "%1$@ mudou o avatar da sala"; "state_event_room_avatar_changed_by_you" = "Vocรช mudou o avatar da sala"; "state_event_room_avatar_removed" = "%1$@ removeu o avatar da sala"; @@ -832,8 +893,14 @@ "state_event_room_name_changed_by_you" = "Vocรช mudou o nome da sala para: %1$@"; "state_event_room_name_removed" = "%1$@ removeu o nome da sala"; "state_event_room_name_removed_by_you" = "Vocรช removeu o nome da sala"; -"state_event_room_none" = "%1$@ made no changes"; -"state_event_room_none_by_you" = "You made no changes"; +"state_event_room_none" = "%1$@ nรฃo fez alteraรงรตes"; +"state_event_room_none_by_you" = "Vocรช nรฃo fez nenhuma alteraรงรฃo"; +"state_event_room_pinned_events_changed" = "%1$@ changed the pinned messages"; +"state_event_room_pinned_events_changed_by_you" = "You changed the pinned messages"; +"state_event_room_pinned_events_pinned" = "%1$@ pinned a message"; +"state_event_room_pinned_events_pinned_by_you" = "You pinned a message"; +"state_event_room_pinned_events_unpinned" = "%1$@ unpinned a message"; +"state_event_room_pinned_events_unpinned_by_you" = "You unpinned a message"; "state_event_room_reject" = "%1$@ rejeitou o convite"; "state_event_room_reject_by_you" = "Vocรช rejeitou o convite"; "state_event_room_remove" = "%1$@ removido %2$@"; @@ -898,7 +965,7 @@ "dialog_title_success" = "Sucesso"; "notification_fallback_content" = "Notificaรงรฃo"; "notification_invitation_action_join" = "Entrar"; -"notification_room_action_mark_as_read" = "Mark as read"; +"notification_room_action_mark_as_read" = "Marcar como lido"; "notification_room_action_quick_reply" = "Resposta rรกpida"; "screen_room_mentions_at_room_title" = "Todos"; "screen_account_provider_signin_subtitle" = "Aqui รฉ onde suas conversas vรฃo ficar โ€” assim como vocรช usa um provedor de e-mails para manter seus e-mails."; @@ -921,21 +988,22 @@ "screen_dm_details_unblock_user" = "Desbloquear usuรกrio"; "screen_edit_poll_delete_confirmation_title" = "Excluir Enquete"; "screen_edit_poll_title" = "Editar enquete"; +"screen_identity_use_another_device" = "Usar outro dispositivo"; "screen_login_subtitle" = "A Matrix รฉ uma rede aberta para comunicaรงรฃo segura e descentralizada."; "screen_qr_code_login_invalid_scan_state_retry_button" = "Tente novamente"; "screen_report_content_block_user" = "Bloquear usuรกrio"; "screen_room_attachment_source_camera_photo" = "Tirar foto"; "screen_room_change_permissions_everyone" = "Todos"; -"screen_room_change_permissions_member_moderation" = "Member moderation"; -"screen_room_change_permissions_messages_and_content" = "Messages and content"; -"screen_room_change_permissions_room_details" = "Room details"; -"screen_room_change_role_section_administrators" = "Admins"; -"screen_room_change_role_section_moderators" = "Moderators"; -"screen_room_change_role_section_users" = "Members"; +"screen_room_change_permissions_member_moderation" = "Moderaรงรฃo de membros"; +"screen_room_change_permissions_messages_and_content" = "Mensagens e conteรบdo"; +"screen_room_change_permissions_room_details" = "Detalhes da sala"; +"screen_room_change_role_section_administrators" = "Administradores"; +"screen_room_change_role_section_moderators" = "Moderadores"; +"screen_room_change_role_section_users" = "Membros"; "screen_room_details_invite_people_title" = "Convidar pessoas"; "screen_room_details_leave_conversation_title" = "Sair da conversa"; "screen_room_details_leave_room_title" = "Sair da sala"; -"screen_room_details_roles_and_permissions" = "Roles and permissions"; +"screen_room_details_roles_and_permissions" = "Cargos e permissรตes"; "screen_room_details_room_name_label" = "Nome da sala"; "screen_room_details_security_title" = "Seguranรงa"; "screen_room_details_topic_title" = "Tรณpico"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "Sair"; "screen_signout_confirmation_dialog_title" = "Sair"; "screen_signout_preference_item" = "Sair"; -"screen_waitlist_message_success" = "Bem-vindo ao %1$@!"; diff --git a/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.stringsdict index 41ea2b47d4..7c41ae03e3 100644 --- a/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.stringsdict @@ -13,9 +13,9 @@ NSStringFormatValueTypeKey d one - %1$d digit entered + %1$d dรญgito inserido other - %1$d digits entered + %1$d dรญgitos inseridos a11y_read_receipts_multiple_with_others @@ -29,9 +29,9 @@ NSStringFormatValueTypeKey d one - Read by %1$@ and %2$d other + Lido por %1$@ e %2$d outro other - Read by %1$@ and %2$d others + Lido por %1$@ e %2$d outros common_member_count @@ -194,6 +194,22 @@ PIN incorreto. Vocรช tem mais %1$d 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 @@ -221,9 +237,9 @@ NSStringFormatValueTypeKey d one - %1$d mudanรงa de sala + %1$d alteraรงรฃo na sala other - %1$d mudanรงas de salas + %1$d alteraรงรตes na sala screen_room_typing_many_members @@ -237,9 +253,9 @@ NSStringFormatValueTypeKey d one - %1$@, %2$@ and %3$d other + %1$@, %2$@ e %3$d outro other - %1$@, %2$@ and %3$d others + %1$@, %2$@ e %3$d outros screen_room_typing_many_members_second_component_ios @@ -253,9 +269,9 @@ NSStringFormatValueTypeKey d one - %d other + %d outro other - %d others + %d outros screen_room_typing_notification @@ -269,9 +285,9 @@ NSStringFormatValueTypeKey d one - %1$@ is typing + %1$@ estรก digitando other - %1$@ are typing + %1$@ estรฃo digitando troubleshoot_notifications_test_detect_push_provider_success diff --git a/ElementX/Resources/Localizations/pt.lproj/Localizable.strings b/ElementX/Resources/Localizations/pt.lproj/Localizable.strings index 0ac00f4337..b385910f11 100644 --- a/ElementX/Resources/Localizations/pt.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/pt.lproj/Localizable.strings @@ -27,17 +27,20 @@ "action_back" = "Voltar"; "action_call" = "Chamar"; "action_cancel" = "Cancelar"; +"action_cancel_for_now" = "Cancel for now"; "action_choose_photo" = "Escolher foto"; "action_clear" = "Limpar"; "action_close" = "Fechar"; "action_complete_verification" = "Concluir verificaรงรฃo"; "action_confirm" = "Confirmar"; +"action_confirm_password" = "Confirm password"; "action_continue" = "Continuar"; "action_copy" = "Copiar"; "action_copy_link" = "Copiar ligaรงรฃo"; "action_copy_link_to_message" = "Copiar ligaรงรฃo da mensagem"; "action_create" = "Criar"; "action_create_a_room" = "Criar uma sala"; +"action_deactivate" = "Deactivate"; "action_decline" = "Rejeitar"; "action_delete_poll" = "Eliminar sondagem"; "action_disable" = "Desativar"; @@ -70,6 +73,7 @@ "action_ok" = "OK"; "action_open_settings" = "Configuraรงรตes"; "action_open_with" = "Abrir com"; +"action_pin" = "Afixar"; "action_quick_reply" = "Resposta rรกpida"; "action_quote" = "Citaรงรฃo"; "action_react" = "Reagir"; @@ -80,6 +84,7 @@ "action_report_bug" = "Comunicar problema"; "action_report_content" = "Denunciar conteรบdo"; "action_reset" = "Repor"; +"action_reset_identity" = "Repor identidade"; "action_retry" = "Tentar novamente"; "action_retry_decryption" = "Tentar decifragem novamente"; "action_save" = "Guardar"; @@ -99,10 +104,18 @@ "action_take_photo" = "Tirar foto"; "action_tap_for_options" = "Toca para ver as opรงรตes"; "action_try_again" = "Tentar novamente"; +"action_unpin" = "Desafixar"; +"action_view_in_timeline" = "View in timeline"; "action_view_source" = "Ver fonte"; "action_yes" = "Sim"; "action.load_more" = "Carrega mais"; -"action.pin" = "Pin"; +"action_deactivate_account" = "Deactivate account"; +"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" = "Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices."; +"banner.set_up_recovery.title" = "Set up recovery"; "common_about" = "Sobre"; "common_acceptable_use_policy" = "Polรญtica de utilizaรงรฃo aceitรกvel"; "common_advanced_settings" = "Configuraรงรตes avanรงadas"; @@ -213,7 +226,8 @@ "common_waiting" = "A aguardarโ€ฆ"; "common_waiting_for_decryption_key" = "ร€ espera desta mensagem"; "common.do_not_show_this_again" = "Nรฃo mostrar novamente"; -"common.open_source_licenses" = "Open source licenses"; +"common.open_source_licenses" = "Licenรงas de cรณdigo aberto"; +"common.pinned" = "Pinned"; "common.send_to" = "Enviar para"; "common_no_room_name" = "Sala sem nome"; "common_poll_end_confirmation" = "Tens a certeza que queres concluir esta sondagem?"; @@ -244,6 +258,7 @@ "emoji_picker_category_people" = "Caras e Pessoas"; "emoji_picker_category_places" = "Viagens e Lugares"; "emoji_picker_category_symbols" = "Sรญmbolos"; +"error_account_creation_not_possible" = "Your homeserver needs to be upgraded to support Matrix Authentication Service and account creation."; "error_failed_creating_the_permalink" = "Falha ao criar ligaรงรฃo permanente"; "error_failed_loading_map" = "%1$@ nรฃo foi possรญvel carregar o mapa. Por favor, tente novamente mais tarde."; "error_failed_loading_messages" = "Falha ao carregar mensagens"; @@ -253,10 +268,12 @@ "error_no_compatible_app_found" = "Nenhuma aplicaรงรฃo encontrada capaz de continuar esta aรงรฃo."; "error_some_messages_have_not_been_sent" = "Algumas mensagens nรฃo foram enviadas"; "error_unknown" = "Ocorreu um erro, desculpa"; -"event_shield_reason_authenticity_not_guaranteed" = "The authenticity of this encrypted message can't be guaranteed on this device."; -"event_shield_reason_unknown_device" = "Encrypted by an unknown or deleted device."; -"event_shield_reason_unsigned_device" = "Encrypted by a device not verified by its owner."; -"event_shield_reason_unverified_identity" = "Encrypted by an unverified user."; +"event_shield_reason_authenticity_not_guaranteed" = "A autenticidade desta mensagem cifrada nรฃo pode ser garantida neste dispositivo."; +"event_shield_reason_previously_verified" = "Encrypted by a previously-verified user."; +"event_shield_reason_sent_in_clear" = "Not encrypted."; +"event_shield_reason_unknown_device" = "Cifragem com origem num dispositivo eliminado ou desconhecido."; +"event_shield_reason_unsigned_device" = "Cifragem com origem num dispositivo nรฃo verificado pelo seu dono."; +"event_shield_reason_unverified_identity" = "Cifragem com origem num utilizador nรฃo verificado."; "full_screen_intent_banner_message" = "Para garantir que nunca perdes uma chamada importante, altera as configuraรงรตes para permitir notificaรงรตes em ecrรฃ inteiro quando o telemรณvel estรก bloqueado."; "full_screen_intent_banner_title" = "Melhora a tua experiรชncia de chamada"; "invite_friends_rich_title" = "๐Ÿ”๏ธ Junta-te a mim na %1$@"; @@ -275,11 +292,14 @@ "notification_inline_reply_failed" = "** Falha no envio - por favor abre a sala"; "notification_invitation_action_reject" = "Rejeitar"; "notification_invite_body" = "Convidou-te para conversar"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "notification_mentioned_you_body" = "Mencionou-te: %1$@"; "notification_new_messages" = "Mensagens novas"; "notification_reaction_body" = "Reagiu com %1$@"; "notification_room_invite_body" = "Convidou-te a entrar na sala"; +"notification_room_invite_body_with_sender" = "%1$@ invited you to join the room"; "notification_sender_me" = "Eu"; +"notification_sender_mention_reply" = "%1$@ mentioned or replied"; "notification_test_push_notification_content" = "Estรกs a ver a notificaรงรฃo! Clica em mim!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -312,10 +332,27 @@ "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_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_pinned_timeline_screen_title_empty" = "Pinned messages"; +"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" = "Notificar toda a sala"; -"screen.room.pinned_banner_indicator" = "%1$@ of %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ Pinned messages"; -"screen.room.pinned_banner_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" = "Loading messageโ€ฆ"; +"screen_room_pinned_banner_view_all_button_title" = "Ver todas"; +"screen_room_details_pinned_events_row_title" = "Pinned messages"; +"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_account_provider_change" = "Alterar operador de conta"; "screen_account_provider_form_hint" = "Endereรงo do servidor"; "screen_account_provider_form_notice" = "Insira um termo para pesquisa ou um endereรงo."; @@ -398,6 +435,7 @@ "screen_chat_backup_recovery_action_confirm_description" = "A tua cรณpia de seguranรงa das conversas estรก atualmente dessincronizada."; "screen_chat_backup_recovery_action_setup" = "Configurar recuperaรงรฃo"; "screen_chat_backup_recovery_action_setup_description" = "Obtรฉm acesso ร s tuas mensagens cifradas mesmo se perderes todos os teus dispositivos ou se terminares todas as tuas sessรตes %1$@."; +"screen_create_account_title" = "Create account"; "screen_create_new_recovery_key_list_item_1" = "Abre a %1$@ num computador"; "screen_create_new_recovery_key_list_item_2" = "Iniciar sessรฃo novamente"; "screen_create_new_recovery_key_list_item_3" = "Quando te for pedido para verificares o teu dispositivo, seleciona %1$@"; @@ -421,6 +459,17 @@ "screen_create_room_public_option_description" = "As mensagens nรฃo serรฃo cifradas e qualquer um as poderรก ler. ร‰ possรญvel ativar a cifragem posteriormente."; "screen_create_room_public_option_title" = "Sala pรบblica (entrada livre)"; "screen_create_room_topic_label" = "Descriรงรฃo (opcional)"; +"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_edit_poll_delete_confirmation" = "Tens a certeza que queres apagar esta sondagem?"; "screen_edit_profile_display_name" = "Pseudรณnimo"; "screen_edit_profile_display_name_placeholder" = "O teu pseudรณnimo"; @@ -428,12 +477,20 @@ "screen_edit_profile_error_title" = "Nรฃo foi possรญvel atualizar o perfil"; "screen_edit_profile_title" = "Editar perfil"; "screen_edit_profile_updating_details" = "A atualizar o perfilโ€ฆ"; +"screen_encryption_reset_action_continue_reset" = "Continue reset"; +"screen_encryption_reset_bullet_1" = "Os detalhes da tua conta, contactos, preferรชncias e lista de conversas serรฃo mantidos."; +"screen_encryption_reset_bullet_2" = "Perderรกs o acesso ao teu histรณrico de mensagens existente"; +"screen_encryption_reset_bullet_3" = "Necessitarรกs de verificar todos os teus dispositivos e contactos novamente."; +"screen_encryption_reset_footer" = "Repรตe a tua identidade apenas se nรฃo tiveres acesso a mais nenhum dispositivo com sessรฃo iniciada e se tiveres perdido a tua chave de recuperaรงรฃo."; +"screen_encryption_reset_title" = "Repรตe a tua identidade caso nรฃo consigas confirmar de outra forma"; +"screen_identity_confirmation_cannot_confirm" = "Nรฃo รฉ possรญvel confirmar?"; "screen_identity_confirmation_create_new_recovery_key" = "Criar uma nova chave de recuperaรงรฃo"; "screen_identity_confirmation_subtitle" = "Verifica este dispositivo para configurar o envio seguro de mensagens."; "screen_identity_confirmation_title" = "Confirma que รฉs tu"; +"screen_identity_confirmation_use_another_device" = "Utilizar outro dispositivo"; +"screen_identity_confirmation_use_recovery_key" = "Utilizar chave de recuperaรงรฃo"; "screen_identity_confirmed_subtitle" = "Agora podes ler ou enviar mensagens de forma segura, e qualquer pessoa com quem converses tambรฉm pode confiar neste dispositivo."; "screen_identity_confirmed_title" = "Dispositivo verificado"; -"screen_identity_use_another_device" = "Utilizar outro dispositivo"; "screen_identity_waiting_on_other_device" = "A aguardar por outros dispositivosโ€ฆ"; "screen_invites_decline_chat_message" = "Tens a certeza que queres rejeitar o convite para %1$@?"; "screen_invites_decline_chat_title" = "Rejeitar conite"; @@ -556,7 +613,6 @@ "screen_recovery_key_confirm_error_content" = "Por favor, tenta novamente para confirmar o acesso ร  tua cรณpia de seguranรงa das conversas."; "screen_recovery_key_confirm_error_title" = "Chave de recuperaรงรฃo incorreta"; "screen_recovery_key_confirm_key_description" = "Tambรฉm funciona se tiveres uma chave ou frase de seguranรงa."; -"screen_recovery_key_confirm_key_label" = "Chave ou cรณdigo de recuperaรงรฃo"; "screen_recovery_key_confirm_key_placeholder" = "Inserir..."; "screen_recovery_key_confirm_lost_recovery_key" = "Perdeste a tua chave?"; "screen_recovery_key_confirm_success" = "Chave de recuperaรงรฃo confirmada"; @@ -577,6 +633,14 @@ "screen_report_content_block_user_hint" = "Ativar para esconder todas as atuais e futuras mensagens deste utilizador"; "screen_report_content_explanation" = "Esta mensagem serรก denunciada ao administrador do teu servidor. Porรฉm, nรฃo lhe serรก possรญvel ler quaisquer mensagens cifradas."; "screen_report_content_hint" = "Razรฃo de denรบncia"; +"screen_reset_encryption_confirmation_alert_action" = "Sim, repor agora"; +"screen_reset_encryption_confirmation_alert_subtitle" = "Este processo รฉ irreversรญvel."; +"screen_reset_encryption_confirmation_alert_title" = "Tens a certeza que pretendes repor a tua cifra?"; +"screen_reset_encryption_password_placeholder" = "Inserirโ€ฆ"; +"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" = "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_room_alias_resolver_resolve_alias_failure" = "Nรฃo foi possรญvel encontrar esse endereรงo de sala"; "screen_room_attachment_source_camera" = "Cรขmara"; "screen_room_attachment_source_camera_video" = "Gravar vรญdeo"; @@ -775,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "Guardaste a tua chave de recuperaรงรฃo?"; "screen_start_chat_error_starting_chat" = "Ocorreu um erro ao tentar iniciar uma conversa"; "screen_view_location_title" = "Localizaรงรฃo"; -"screen_waitlist_message" = "Hรก uma grande procura pela %1$@ no %2$@, de momento. Volta ร  aplicaรงรฃo daqui a uns dias e tenta novamente.\n\nObrigado!"; -"screen_waitlist_title" = "Estรกs quase lรก."; -"screen_waitlist_title_success" = "Estรกs dentro."; "screen_welcome_bullet_1" = "Chamadas, sondagens, pesquisa e mais funcionalidades vรฃo ser adicionadas ao longo do ano."; "screen_welcome_bullet_2" = "O histรณrico de mensagens em salas cifradas ainda nรฃo estรก disponรญvel."; "screen_welcome_bullet_3" = "Gostarรญamos de ouvir a tua opiniรฃo, diz-nos o que pensas atravรฉs da pรกgina de configuraรงรตes."; @@ -834,6 +895,12 @@ "state_event_room_name_removed_by_you" = "Removeste o nome da sala"; "state_event_room_none" = "%1$@ nรฃo fiz nenhuma alteraรงรฃo"; "state_event_room_none_by_you" = "Nรฃo fizeste nenhuma alteraรงรฃo"; +"state_event_room_pinned_events_changed" = "%1$@ alterou as mensagens afixadas"; +"state_event_room_pinned_events_changed_by_you" = "Alteraste as mensagens afixadas"; +"state_event_room_pinned_events_pinned" = "%1$@ afixou uma mensagem"; +"state_event_room_pinned_events_pinned_by_you" = "Afixaste uma mensagem"; +"state_event_room_pinned_events_unpinned" = "%1$@ desafixou uma mensagem"; +"state_event_room_pinned_events_unpinned_by_you" = "Desafixaste uma mensagem"; "state_event_room_reject" = "%1$@ rejeitou o convite"; "state_event_room_reject_by_you" = "Rejeitaste o convite"; "state_event_room_remove" = "%1$@ removeu %2$@"; @@ -921,6 +988,7 @@ "screen_dm_details_unblock_user" = "Desbloquear utilizador"; "screen_edit_poll_delete_confirmation_title" = "Eliminar sondagem"; "screen_edit_poll_title" = "Editar sondagem"; +"screen_identity_use_another_device" = "Utilizar outro dispositivo"; "screen_login_subtitle" = "A Matrix รฉ uma rede aberta de comunicaรงรฃo descentralizada e segura."; "screen_qr_code_login_invalid_scan_state_retry_button" = "Tentar novamente"; "screen_report_content_block_user" = "Bloquear utilizador"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "Terminar sessรฃo"; "screen_signout_confirmation_dialog_title" = "Terminar sessรฃo"; "screen_signout_preference_item" = "Terminar sessรฃo"; -"screen_waitlist_message_success" = "Bem-vindo ร  %1$@!"; diff --git a/ElementX/Resources/Localizations/pt.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/pt.lproj/Localizable.stringsdict index ff02239e14..be8835fae3 100644 --- a/ElementX/Resources/Localizations/pt.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/pt.lproj/Localizable.stringsdict @@ -194,6 +194,22 @@ PIN incorreto. Tens mais %1$d tentativas + 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 diff --git a/ElementX/Resources/Localizations/ro.lproj/Localizable.strings b/ElementX/Resources/Localizations/ro.lproj/Localizable.strings index 8f2957f9d6..595d4b3690 100644 --- a/ElementX/Resources/Localizations/ro.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/ro.lproj/Localizable.strings @@ -27,17 +27,20 @@ "action_back" = "รŽnapoi"; "action_call" = "Apel"; "action_cancel" = "Anulaศ›i"; +"action_cancel_for_now" = "Cancel for now"; "action_choose_photo" = "Alegeศ›i o fotografie"; "action_clear" = "ศ˜tergeศ›i"; "action_close" = "รŽnchideศ›i"; "action_complete_verification" = "Verificare completฤƒ"; "action_confirm" = "Confirmaศ›i"; +"action_confirm_password" = "Confirm password"; "action_continue" = "Continuaศ›i"; "action_copy" = "Copiaศ›i"; "action_copy_link" = "Copiaศ›i linkul"; "action_copy_link_to_message" = "Copiaศ›i linkul cฤƒtre mesaj"; "action_create" = "Creaศ›i"; "action_create_a_room" = "Creaศ›i o camerฤƒ"; +"action_deactivate" = "Deactivate"; "action_decline" = "Refuzaศ›i"; "action_delete_poll" = "ศ˜tergeศ›i sondajul"; "action_disable" = "Dezactivaศ›i"; @@ -70,6 +73,7 @@ "action_ok" = "OK"; "action_open_settings" = "Setฤƒri"; "action_open_with" = "Deschideศ›i cu"; +"action_pin" = "Pin"; "action_quick_reply" = "Raspuns rapid"; "action_quote" = "Citat"; "action_react" = "Reacศ›ionaศ›i"; @@ -80,6 +84,7 @@ "action_report_bug" = "Raportaศ›i o eroare"; "action_report_content" = "Raportaศ›i conศ›inutul"; "action_reset" = "Resetare"; +"action_reset_identity" = "Reset identity"; "action_retry" = "Reรฎncercaศ›i"; "action_retry_decryption" = "Reรฎncercaศ›i decriptarea"; "action_save" = "Salvaศ›i"; @@ -99,10 +104,18 @@ "action_take_photo" = "Faceศ›i o fotografie"; "action_tap_for_options" = "Atingeศ›i pentru opศ›iuni"; "action_try_again" = "รŽncercaศ›i din nou"; +"action_unpin" = "Unpin"; +"action_view_in_timeline" = "View in timeline"; "action_view_source" = "Vedeศ›i sursฤƒ"; "action_yes" = "Da"; "action.load_more" = "รŽncฤƒrcaศ›i mai mult"; -"action.pin" = "Pin"; +"action_deactivate_account" = "Deactivate account"; +"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" = "Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices."; +"banner.set_up_recovery.title" = "Set up recovery"; "common_about" = "Despre"; "common_acceptable_use_policy" = "Politicฤƒ de utilizare rezonabilฤƒ"; "common_advanced_settings" = "Setฤƒri avansate"; @@ -214,6 +227,7 @@ "common_waiting_for_decryption_key" = "Mesaj รฎn aศ™teptare"; "common.do_not_show_this_again" = "Do not show this again"; "common.open_source_licenses" = "Open source licenses"; +"common.pinned" = "Pinned"; "common.send_to" = "Trimiteศ›i cฤƒtre"; "common_no_room_name" = "Fฤƒrฤƒ nume de camerฤƒ"; "common_poll_end_confirmation" = "Sunteศ›i sigur cฤƒ doriศ›i sฤƒ รฎncheiaศ›i acest sondaj?"; @@ -244,6 +258,7 @@ "emoji_picker_category_people" = "Feศ›e zรขmbitoare & Oameni"; "emoji_picker_category_places" = "Cฤƒlฤƒtorii & Locuri"; "emoji_picker_category_symbols" = "Simboluri"; +"error_account_creation_not_possible" = "Your homeserver needs to be upgraded to support Matrix Authentication Service and account creation."; "error_failed_creating_the_permalink" = "Crearea permalink-ului a eศ™uat"; "error_failed_loading_map" = "%1$@ nu a putut รฎncฤƒrca harta. Vฤƒ rugฤƒm sฤƒ รฎncercaศ›i din nou mai tรขrziu."; "error_failed_loading_messages" = "รŽncฤƒrcarea mesajelor a eศ™uat"; @@ -254,6 +269,8 @@ "error_some_messages_have_not_been_sent" = "Unele mesaje nu au fost trimise"; "error_unknown" = "Ne pare rฤƒu, a apฤƒrut o eroare"; "event_shield_reason_authenticity_not_guaranteed" = "The authenticity of this encrypted message can't be guaranteed on this device."; +"event_shield_reason_previously_verified" = "Encrypted by a previously-verified user."; +"event_shield_reason_sent_in_clear" = "Not encrypted."; "event_shield_reason_unknown_device" = "Encrypted by an unknown or deleted device."; "event_shield_reason_unsigned_device" = "Encrypted by a device not verified by its owner."; "event_shield_reason_unverified_identity" = "Encrypted by an unverified user."; @@ -275,11 +292,14 @@ "notification_inline_reply_failed" = "** Trimiterea eศ™uatฤƒ - vฤƒ rugฤƒm sฤƒ deschideศ›i camera"; "notification_invitation_action_reject" = "Respingeศ›i"; "notification_invite_body" = "V-a invitat la o discuศ›ie"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "notification_mentioned_you_body" = "%1$@ v-a menศ›ionat"; "notification_new_messages" = "Mesaje noi"; "notification_reaction_body" = "A reacศ›ionat cu %1$@"; "notification_room_invite_body" = "V-a invitat sฤƒ vฤƒ alฤƒturaศ›i camerei"; +"notification_room_invite_body_with_sender" = "%1$@ invited you to join the room"; "notification_sender_me" = "Eu"; +"notification_sender_mention_reply" = "%1$@ mentioned or replied"; "notification_test_push_notification_content" = "Vizualizaศ›i o notificare! Faceศ›i clic pe mine!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -312,10 +332,27 @@ "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_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_pinned_timeline_screen_title_empty" = "Pinned messages"; +"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" = "Notificaศ›i รฎntreaga camerฤƒ"; -"screen.room.pinned_banner_indicator" = "%1$@ of %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ Pinned messages"; -"screen.room.pinned_banner_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_details_pinned_events_row_title" = "Pinned messages"; +"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_account_provider_change" = "Schimbaศ›i furnizorul contului"; "screen_account_provider_form_hint" = "Adresa Homeserver-ului"; "screen_account_provider_form_notice" = "Introduceลฃi un termen de cฤƒutare sau o adresฤƒ de domeniu."; @@ -398,6 +435,7 @@ "screen_chat_backup_recovery_action_confirm_description" = "Backup-ul pentru chat nu este sincronizat รฎn prezent."; "screen_chat_backup_recovery_action_setup" = "Configuraศ›i recuperarea"; "screen_chat_backup_recovery_action_setup_description" = "Obศ›ineศ›i acces la mesajele dumneavoastrฤƒ criptate dacฤƒ vฤƒ pierdeศ›i toate dispozitivele sau sunteศ›i deconectat de la %1$@ peste tot."; +"screen_create_account_title" = "Create account"; "screen_create_new_recovery_key_list_item_1" = "Deschideศ›i %1$@ pe un dispozitiv desktop"; "screen_create_new_recovery_key_list_item_2" = "Conectaศ›i-vฤƒ din nou la contul dumneavoastrฤƒ"; "screen_create_new_recovery_key_list_item_3" = "Cรขnd vi se cere sฤƒ vฤƒ verificaศ›i dispozitivul, selectaศ›i%1$@"; @@ -421,6 +459,17 @@ "screen_create_room_public_option_description" = "Mesajele nu sunt criptate ศ™i oricine le poate citi. Puteศ›i activa criptarea la o datฤƒ ulterioarฤƒ."; "screen_create_room_public_option_title" = "Camerฤƒ publicฤƒ (oricine)"; "screen_create_room_topic_label" = "Subiect (opศ›ional)"; +"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_edit_poll_delete_confirmation" = "Sunteศ›i sigur cฤƒ doriศ›i sฤƒ ศ™tergeศ›i acest sondaj?"; "screen_edit_profile_display_name" = "Nume"; "screen_edit_profile_display_name_placeholder" = "Numele dumneavoastra"; @@ -428,12 +477,20 @@ "screen_edit_profile_error_title" = "Nu s-a putut actualiza profilul"; "screen_edit_profile_title" = "Editaศ›i profilul"; "screen_edit_profile_updating_details" = "Se actualizeazฤƒ profilul..."; +"screen_encryption_reset_action_continue_reset" = "Continue reset"; +"screen_encryption_reset_bullet_1" = "Your account details, contacts, preferences, and chat list will be kept"; +"screen_encryption_reset_bullet_2" = "You will lose your existing message history"; +"screen_encryption_reset_bullet_3" = "You will need to verify all your existing devices and contacts again"; +"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_identity_confirmation_create_new_recovery_key" = "Creaศ›i o nouฤƒ cheie de recuperare"; "screen_identity_confirmation_subtitle" = "Verificaศ›i acest dispozitiv pentru a configura mesagerie securizatฤƒ."; "screen_identity_confirmation_title" = "Confirmaศ›i cฤƒ sunteศ›i dumneavoastrฤƒ"; +"screen_identity_confirmation_use_another_device" = "Utilizaศ›i un alt dispozitiv"; +"screen_identity_confirmation_use_recovery_key" = "Use recovery key"; "screen_identity_confirmed_subtitle" = "Acum puteศ›i citi sau trimite mesaje รฎn siguranศ›ฤƒ, iar oricine cu care conversaศ›i poate avea รฎncredere รฎn acest dispozitiv."; "screen_identity_confirmed_title" = "Dispozitiv verificat"; -"screen_identity_use_another_device" = "Utilizaศ›i un alt dispozitiv"; "screen_identity_waiting_on_other_device" = "Se aศ™teaptฤƒ celฤƒlalt dispozitiv..."; "screen_invites_decline_chat_message" = "Sigur doriศ›i sฤƒ refuzaศ›i alฤƒturarea la %1$@?"; "screen_invites_decline_chat_title" = "Refuzaศ›i invitaศ›ia"; @@ -556,7 +613,6 @@ "screen_recovery_key_confirm_error_content" = "Vฤƒ rugฤƒm sฤƒ รฎncercaศ›i din nou sฤƒ confirmaศ›i accesul la backup."; "screen_recovery_key_confirm_error_title" = "Cheie de recuperare incorectฤƒ"; "screen_recovery_key_confirm_key_description" = "Dacฤƒ aveศ›i o cheie de securitate sau o frazฤƒ de securitate, aceasta va funcศ›iona ศ™i ea."; -"screen_recovery_key_confirm_key_label" = "Cheie de recuperare sau cod de acces"; "screen_recovery_key_confirm_key_placeholder" = "Introduceศ›i..."; "screen_recovery_key_confirm_lost_recovery_key" = "Aศ›i pierdut cheia de recuperare?"; "screen_recovery_key_confirm_success" = "Cheia de recuperare confirmatฤƒ"; @@ -577,6 +633,14 @@ "screen_report_content_block_user_hint" = "Confirmaศ›i cฤƒ doriศ›i sฤƒ ascundeศ›i toate mesajele curente ศ™i viitoare de la acest utilizator"; "screen_report_content_explanation" = "Acest mesaj va fi raportat administratorilor homeserver-ului tau. Ei nu vor putea citi niciun mesaj criptat."; "screen_report_content_hint" = "Motivul raportฤƒrii acestui conศ›inut"; +"screen_reset_encryption_confirmation_alert_action" = "Yes, reset now"; +"screen_reset_encryption_confirmation_alert_subtitle" = "This process is irreversible."; +"screen_reset_encryption_confirmation_alert_title" = "Are you sure you want to reset your identity?"; +"screen_reset_encryption_password_placeholder" = "Enterโ€ฆ"; +"screen_reset_encryption_password_subtitle" = "Confirm that you want to reset your identity."; +"screen_reset_encryption_password_title" = "Enter your account password to continue"; +"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_room_alias_resolver_resolve_alias_failure" = "Nu s-a putut rezolva alias-ul camerei."; "screen_room_attachment_source_camera" = "Camerฤƒ foto"; "screen_room_attachment_source_camera_video" = "รŽnregistraศ›i un videoclip"; @@ -775,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "Aศ›i salvat cheia de recuperare?"; "screen_start_chat_error_starting_chat" = "A apฤƒrut o eroare la รฎncercarea รฎnceperii conversaศ›iei"; "screen_view_location_title" = "Locaศ›ie"; -"screen_waitlist_message" = "Existฤƒ o cerere mare pentru %1$@ pentru %2$@ รฎn acest moment. Reveniศ›i la aplicaศ›ie รฎn cรขteva zile ศ™i รฎncercaศ›i din nou.\n\nVฤƒ mulศ›umim pentru rฤƒbdare!"; -"screen_waitlist_title" = "Sunteศ›i pe lista de aศ™teptare"; -"screen_waitlist_title_success" = "Sunteศ›i conectat!"; "screen_welcome_bullet_1" = "Apelurile, sondajele, cฤƒutare ศ™i multe altele vor fi adฤƒugate รฎn cursul acestui an."; "screen_welcome_bullet_2" = "Istoricul mesajelor pentru camerele criptate nu va fi disponibil รฎn aceastฤƒ actualizare."; "screen_welcome_bullet_3" = "Ne-ar plฤƒcea sฤƒ auzim de la dumneavoastrฤƒ, spuneศ›i-ne ce pฤƒrere aveศ›i prin intermediul paginii de setฤƒri."; @@ -834,6 +895,12 @@ "state_event_room_name_removed_by_you" = "Aศ›i ศ™ters numele camerei"; "state_event_room_none" = "%1$@ nu a fฤƒcut nicio modificare"; "state_event_room_none_by_you" = "Nu aศ›i fฤƒcut nicio modificare"; +"state_event_room_pinned_events_changed" = "%1$@ changed the pinned messages"; +"state_event_room_pinned_events_changed_by_you" = "You changed the pinned messages"; +"state_event_room_pinned_events_pinned" = "%1$@ pinned a message"; +"state_event_room_pinned_events_pinned_by_you" = "You pinned a message"; +"state_event_room_pinned_events_unpinned" = "%1$@ unpinned a message"; +"state_event_room_pinned_events_unpinned_by_you" = "You unpinned a message"; "state_event_room_reject" = "%1$@ a respins invitaศ›ia"; "state_event_room_reject_by_you" = "Aศ›i respins invitaศ›ia"; "state_event_room_remove" = "%1$@ l-a รฎndepฤƒrtat pe %2$@"; @@ -921,6 +988,7 @@ "screen_dm_details_unblock_user" = "Deblocaศ›i utilizatorul"; "screen_edit_poll_delete_confirmation_title" = "ศ˜tergeศ›i sondajul"; "screen_edit_poll_title" = "Editaศ›i sondajul"; +"screen_identity_use_another_device" = "Utilizaศ›i un alt dispozitiv"; "screen_login_subtitle" = "Matrix este o reศ›ea deschisฤƒ pentru o comunicare sigurฤƒ ศ™i descentralizatฤƒ."; "screen_qr_code_login_invalid_scan_state_retry_button" = "รŽncercaศ›i din nou"; "screen_report_content_block_user" = "Blocaศ›i utilizatorul"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "Deconectaศ›i-vฤƒ"; "screen_signout_confirmation_dialog_title" = "Deconectaศ›i-vฤƒ"; "screen_signout_preference_item" = "Deconectaศ›i-vฤƒ"; -"screen_waitlist_message_success" = "Bun venit la%1$@!"; diff --git a/ElementX/Resources/Localizations/ro.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/ro.lproj/Localizable.stringsdict index 91fd4f3f7d..18f7fe5b53 100644 --- a/ElementX/Resources/Localizations/ro.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/ro.lproj/Localizable.stringsdict @@ -206,6 +206,22 @@ PIN greศ™it. Mai aveศ›i %1$d sanse + 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 diff --git a/ElementX/Resources/Localizations/ru.lproj/Localizable.strings b/ElementX/Resources/Localizations/ru.lproj/Localizable.strings index 267091df75..4c044fa74f 100644 --- a/ElementX/Resources/Localizations/ru.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/ru.lproj/Localizable.strings @@ -27,17 +27,20 @@ "action_back" = "ะะฐะทะฐะด"; "action_call" = "ะŸะพะทะฒะพะฝะธั‚ัŒ"; "action_cancel" = "ะžั‚ะผะตะฝะฐ"; +"action_cancel_for_now" = "ะžั‚ะผะตะฝะธั‚ะต ัะตะนั‡ะฐั"; "action_choose_photo" = "ะ’ั‹ะฑั€ะฐั‚ัŒ ั„ะพั‚ะพ"; "action_clear" = "ะžั‡ะธัั‚ะธั‚ัŒ"; "action_close" = "ะ—ะฐะบั€ั‹ั‚ัŒ"; "action_complete_verification" = "ะŸะพะปะฝะฐั ะฟั€ะพะฒะตั€ะบะฐ"; "action_confirm" = "ะŸะพะดั‚ะฒะตั€ะดะธั‚ัŒ"; +"action_confirm_password" = "ะŸะพะดั‚ะฒะตั€ะดะธั‚ะต ะฟะฐั€ะพะปัŒ"; "action_continue" = "ะŸั€ะพะดะพะปะถะธั‚ัŒ"; "action_copy" = "ะšะพะฟะธั€ะพะฒะฐั‚ัŒ"; "action_copy_link" = "ะกะบะพะฟะธั€ะพะฒะฐั‚ัŒ ััั‹ะปะบัƒ"; "action_copy_link_to_message" = "ะกะบะพะฟะธั€ะพะฒะฐั‚ัŒ ััั‹ะปะบัƒ ะฒ ัะพะพะฑั‰ะตะฝะธะต"; "action_create" = "ะกะพะทะดะฐั‚ัŒ"; "action_create_a_room" = "ะกะพะทะดะฐั‚ัŒ ะบะพะผะฝะฐั‚ัƒ"; +"action_deactivate" = "ะ”ะตะฐะบั‚ะธะฒะธั€ะพะฒะฐั‚ัŒ"; "action_decline" = "ะžั‚ะบะปะพะฝะธั‚ัŒ"; "action_delete_poll" = "ะฃะดะฐะปะธั‚ัŒ ะพะฟั€ะพั"; "action_disable" = "ะžั‚ะบะปัŽั‡ะธั‚ัŒ"; @@ -70,6 +73,7 @@ "action_ok" = "ะžะบ"; "action_open_settings" = "ะžั‚ะบั€ั‹ั‚ัŒ ะฝะฐัั‚ั€ะพะนะบะธ"; "action_open_with" = "ะžั‚ะบั€ั‹ั‚ัŒ ั ะฟะพะผะพั‰ัŒัŽ"; +"action_pin" = "ะ—ะฐะบั€ะตะฟะธั‚ัŒ"; "action_quick_reply" = "ะ‘ั‹ัั‚ั€ั‹ะน ะพั‚ะฒะตั‚"; "action_quote" = "ะฆะธั‚ะฐั‚ะฐ"; "action_react" = "ะ ะตะฐะบั†ะธั"; @@ -80,6 +84,7 @@ "action_report_bug" = "ะกะพะพะฑั‰ะธั‚ัŒ ะพะฑ ะพัˆะธะฑะบะต"; "action_report_content" = "ะŸะพะถะฐะปะพะฒะฐั‚ัŒัั ะฝะฐ ัะพะดะตั€ะถะฐะฝะธะต"; "action_reset" = "ะกะฑั€ะพัะธั‚ัŒ"; +"action_reset_identity" = "ะกะฑั€ะพัะธั‚ัŒ ะธะดะตะฝั‚ะธั„ะธะบะฐั†ะธัŽ"; "action_retry" = "ะŸะพะฒั‚ะพั€ะธั‚ัŒ"; "action_retry_decryption" = "ะŸะพะฒั‚ะพั€ะธั‚ะต ั€ะฐััˆะธั„ั€ะพะฒะบัƒ"; "action_save" = "ะกะพั…ั€ะฐะฝะธั‚ัŒ"; @@ -99,10 +104,18 @@ "action_take_photo" = "ะกะดะตะปะฐั‚ัŒ ั„ะพั‚ะพ"; "action_tap_for_options" = "ะะฐะถะผะธั‚ะต ะดะปั ะฟั€ะพัะผะพั‚ั€ะฐ ะฒะฐั€ะธะฐะฝั‚ะพะฒ"; "action_try_again" = "ะŸะพะฒั‚ะพั€ะธั‚ัŒ ะฟะพะฟั‹ั‚ะบัƒ"; +"action_unpin" = "ะžั‚ะบั€ะตะฟะธั‚ัŒ"; +"action_view_in_timeline" = "ะŸั€ะพัะผะพั‚ั€ ะฒ ั…ั€ะพะฝะพะปะพะณะธะธ"; "action_view_source" = "ะŸะพะบะฐะทะฐั‚ัŒ ะธัั‚ะพั‡ะฝะธะบ"; "action_yes" = "ะ”ะฐ"; "action.load_more" = "ะ—ะฐะณั€ัƒะทะธั‚ัŒ ะตั‰ะต"; -"action.pin" = "Pin"; +"action_deactivate_account" = "ะžั‚ะบะปัŽั‡ะธั‚ัŒ ัƒั‡ั‘ั‚ะฝัƒัŽ ะทะฐะฟะธััŒ"; +"banner_migrate_to_native_sliding_sync_action" = "ะ’ั‹ะนั‚ะธ ะธ ะพะฑะฝะพะฒะธั‚ัŒ"; +"banner_migrate_to_native_sliding_sync_description" = "ะขะตะฟะตั€ัŒ ะฒะฐัˆ ัะตั€ะฒะตั€ ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ะฝะพะฒั‹ะน, ะฑะพะปะตะต ะฑั‹ัั‚ั€ั‹ะน ะฟั€ะพั‚ะพะบะพะป. ะ’ั‹ะนะดะธั‚ะต ะธะท ัะธัั‚ะตะผั‹ ะธ ัะฝะพะฒะฐ ะฒะพะนะดะธั‚ะต ะฒ ัะธัั‚ะตะผัƒ ะดะปั ะพะฑะฝะพะฒะปะตะฝะธั ะฟั€ัะผะพ ัะตะนั‡ะฐั. ะกะดะตะปะฐะฒ ัั‚ะพ ัะตะนั‡ะฐั, ะฒั‹ ัะผะพะถะตั‚ะต ะธะทะฑะตะถะฐั‚ัŒ ะฟั€ะธะฝัƒะดะธั‚ะตะปัŒะฝะพะณะพ ะฒั‹ั…ะพะดะฐ ะธะท ัะธัั‚ะตะผั‹ ะฟั€ะธ ะฟะพัะปะตะดัƒัŽั‰ะตะผ ัƒะดะฐะปะตะฝะธะธ ัั‚ะฐั€ะพะณะพ ะฟั€ะพั‚ะพะบะพะปะฐ."; +"banner_migrate_to_native_sliding_sync_force_logout_title" = "ะ’ะฐัˆ homeserver ะฑะพะปัŒัˆะต ะฝะต ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ัั‚ะฐั€ั‹ะน ะฟั€ะพั‚ะพะบะพะป. ะŸะพะถะฐะปัƒะนัั‚ะฐ, ะฒั‹ะนะดะธั‚ะต ะธะท ัะธัั‚ะตะผั‹ ะธ ะฒะพะนะดะธั‚ะต ัะฝะพะฒะฐ, ั‡ั‚ะพะฑั‹ ะฟั€ะพะดะพะปะถะธั‚ัŒ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะต ะฟั€ะธะปะพะถะตะฝะธั."; +"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" = "ะ”ะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต ะฝะฐัั‚ั€ะพะนะบะธ"; @@ -213,7 +226,8 @@ "common_waiting" = "ะžะถะธะดะฐะฝะธะตโ€ฆ"; "common_waiting_for_decryption_key" = "ะžะถะธะดะฐะฝะธะต ะบะปัŽั‡ะฐ ั€ะฐััˆะธั„ั€ะพะฒะบะธ"; "common.do_not_show_this_again" = "ะะต ะฟะพะบะฐะทั‹ะฒะฐั‚ัŒ ะฑะพะปัŒัˆะต"; -"common.open_source_licenses" = "Open source licenses"; +"common.open_source_licenses" = "ะ›ะธั†ะตะฝะทะธะธ ั ะพั‚ะบั€ั‹ั‚ั‹ะผ ะธัั…ะพะดะฝั‹ะผ ะบะพะดะพะผ"; +"common.pinned" = "ะ—ะฐะบั€ะตะฟะปะตะฝะฝั‹ะน"; "common.send_to" = "ะžั‚ะฟั€ะฐะฒะธั‚ัŒ"; "common_no_room_name" = "ะะตั‚ัƒ ะฝะฐะทะฒะฐะฝะธั ะบะพะผะฝะฐั‚ั‹"; "common_poll_end_confirmation" = "ะ’ั‹ ะดะตะนัั‚ะฒะธั‚ะตะปัŒะฝะพ ั…ะพั‚ะธั‚ะต ะทะฐะฒะตั€ัˆะธั‚ัŒ ะดะฐะฝะฝั‹ะน ะพะฟั€ะพั?"; @@ -244,6 +258,7 @@ "emoji_picker_category_people" = "ะฃะปั‹ะฑะบะธ ะธ ะปัŽะดะธ"; "emoji_picker_category_places" = "ะŸัƒั‚ะตัˆะตัั‚ะฒะธั ะธ ะผะตัั‚ะฐ"; "emoji_picker_category_symbols" = "ะกะธะผะฒะพะปั‹"; +"error_account_creation_not_possible" = "ะ’ะฐัˆ homeserver ะฝะตะพะฑั…ะพะดะธะผะพ ะพะฑะฝะพะฒะธั‚ัŒ, ั‡ั‚ะพะฑั‹ ะพะฝ ะฟะพะดะดะตั€ะถะธะฒะฐะป Matrix Authentication Service ะธ ัะพะทะดะฐะฝะธะต ัƒั‡ะตั‚ะฝะพะน ะทะฐะฟะธัะธ."; "error_failed_creating_the_permalink" = "ะะต ัƒะดะฐะปะพััŒ ัะพะทะดะฐั‚ัŒ ะฟะพัั‚ะพัะฝะฝัƒัŽ ััั‹ะปะบัƒ"; "error_failed_loading_map" = "ะะต ัƒะดะฐะปะพััŒ ะทะฐะณั€ัƒะทะธั‚ัŒ ะบะฐั€ั‚ัƒ %1$@. ะŸะพะถะฐะปัƒะนัั‚ะฐ, ะฟะพะฒั‚ะพั€ะธั‚ะต ะฟะพะฟั‹ั‚ะบัƒ ะฟะพะทะถะต."; "error_failed_loading_messages" = "ะะต ัƒะดะฐะปะพััŒ ะทะฐะณั€ัƒะทะธั‚ัŒ ัะพะพะฑั‰ะตะฝะธั"; @@ -253,10 +268,12 @@ "error_no_compatible_app_found" = "ะะต ะฝะฐะนะดะตะฝะพ ัะพะฒะผะตัั‚ะธะผะพะต ะฟั€ะธะปะพะถะตะฝะธะต ะดะปั ะพะฑั€ะฐะฑะพั‚ะบะธ ัั‚ะพะณะพ ะดะตะนัั‚ะฒะธั."; "error_some_messages_have_not_been_sent" = "ะะตะบะพั‚ะพั€ั‹ะต ัะพะพะฑั‰ะตะฝะธั ะฝะต ะฑั‹ะปะธ ะพั‚ะฟั€ะฐะฒะปะตะฝั‹"; "error_unknown" = "ะ˜ะทะฒะธะฝะธั‚ะต, ะฟั€ะพะธะทะพัˆะปะฐ ะพัˆะธะฑะบะฐ"; -"event_shield_reason_authenticity_not_guaranteed" = "The authenticity of this encrypted message can't be guaranteed on this device."; -"event_shield_reason_unknown_device" = "Encrypted by an unknown or deleted device."; -"event_shield_reason_unsigned_device" = "Encrypted by a device not verified by its owner."; -"event_shield_reason_unverified_identity" = "Encrypted by an unverified user."; +"event_shield_reason_authenticity_not_guaranteed" = "ะŸะพะดะปะธะฝะฝะพัั‚ัŒ ัั‚ะพะณะพ ะทะฐัˆะธั„ั€ะพะฒะฐะฝะฝะพะณะพ ัะพะพะฑั‰ะตะฝะธั ะฝะต ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ะณะฐั€ะฐะฝั‚ะธั€ะพะฒะฐะฝะฐ ะฝะฐ ัั‚ะพะผ ัƒัั‚ั€ะพะนัั‚ะฒะต."; +"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$@"; @@ -275,11 +292,14 @@ "notification_inline_reply_failed" = "** ะะต ัƒะดะฐะปะพััŒ ะพั‚ะฟั€ะฐะฒะธั‚ัŒ - ะฟะพะถะฐะปัƒะนัั‚ะฐ, ะพั‚ะบั€ะพะนั‚ะต ะบะพะผะฝะฐั‚ัƒ"; "notification_invitation_action_reject" = "ะžั‚ะบะปะพะฝะธั‚ัŒ"; "notification_invite_body" = "ะŸั€ะธะณะปะฐัะธะป ะฒะฐั ะฒ ั‡ะฐั‚"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "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_sender_me" = "ะฏ"; +"notification_sender_mention_reply" = "%1$@ ัƒะฟะพะผัะฝัƒะป ะธะปะธ ะพั‚ะฒะตั‚ะธะป"; "notification_test_push_notification_content" = "ะ’ั‹ ะฟั€ะพัะผะฐั‚ั€ะธะฒะฐะตั‚ะต ัƒะฒะตะดะพะผะปะตะฝะธะต! ะะฐะถะผะธั‚ะต ะฝะฐ ะผะตะฝั!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -312,10 +332,27 @@ "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_pinned_timeline_empty_state_description" = "ะะฐะถะผะธั‚ะต ะฝะฐ ัะพะพะฑั‰ะตะฝะธะต ะธ ะฒั‹ะฑะตั€ะธั‚ะต โ€œ%1$@โ€, ั‡ั‚ะพะฑั‹ ะดะพะฑะฐะฒะธั‚ัŒ ะตะณะพ ััŽะดะฐ."; +"screen_pinned_timeline_empty_state_headline" = "ะ—ะฐะบั€ะตะฟะธั‚ะต ะฒะฐะถะฝั‹ะต ัะพะพะฑั‰ะตะฝะธั, ั‡ั‚ะพะฑั‹ ะธั… ะผะพะถะฝะพ ะฑั‹ะปะพ ะปะตะณะบะพ ะฝะฐะนั‚ะธ"; +"screen_pinned_timeline_screen_title_empty" = "ะ—ะฐะบั€ะตะฟะปะตะฝะฝั‹ะต ัะพะพะฑั‰ะตะฝะธั"; +"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.pinned_banner_indicator" = "%1$@ of %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ Pinned messages"; -"screen.room.pinned_banner_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_details_pinned_events_row_title" = "ะ—ะฐะบั€ะตะฟะปะตะฝะฝั‹ะต ัะพะพะฑั‰ะตะฝะธั"; +"screen_timeline_item_menu_send_failure_changed_identity" = "ะกะพะพะฑั‰ะตะฝะธะต ะฝะต ะพั‚ะฟั€ะฐะฒะปะตะฝะพ, ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ ะฒะตั€ะธั„ะธั†ะธั€ะพะฒะฐะฝะฝะฐั ะปะธั‡ะฝะพัั‚ัŒ %1$@ ะธะทะผะตะฝะธะปะฐััŒ."; +"screen_timeline_item_menu_send_failure_unsigned_device" = "ะกะพะพะฑั‰ะตะฝะธะต ะฝะต ะพั‚ะฟั€ะฐะฒะปะตะฝะพ, ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ %1$@ ะฝะต ะฟั€ะพะฒะตั€ะธะป ะพะดะฝะพ ะธะปะธ ะฝะตัะบะพะปัŒะบะพ ัƒัั‚ั€ะพะนัั‚ะฒ."; +"screen_timeline_item_menu_send_failure_you_unsigned_device" = "ะกะพะพะฑั‰ะตะฝะธะต ะฝะต ะพั‚ะฟั€ะฐะฒะปะตะฝะพ, ะฟะพัะบะพะปัŒะบัƒ ะฒั‹ ะฝะต ะฟะพะดั‚ะฒะตั€ะดะธะปะธ ะพะดะฝะพ ะธะปะธ ะฝะตัะบะพะปัŒะบะพ ัะฒะพะธั… ัƒัั‚ั€ะพะนัั‚ะฒ."; "screen_account_provider_change" = "ะŸะตั€ะตะบะปัŽั‡ะธั‚ัŒ ะฐะบะบะฐัƒะฝั‚"; "screen_account_provider_form_hint" = "ะะดั€ะตั ะดะพะผะฐัˆะฝะตะณะพ ัะตั€ะฒะตั€ะฐ"; "screen_account_provider_form_notice" = "ะ’ะฒะตะดะธั‚ะต ะฟะพะธัะบะพะฒั‹ะน ะทะฐะฟั€ะพั ะธะปะธ ะฐะดั€ะตั ะดะพะผะตะฝะฐ."; @@ -398,6 +435,7 @@ "screen_chat_backup_recovery_action_confirm_description" = "ะ ะตะทะตั€ะฒะฝะฐั ะบะพะฟะธั ั‡ะฐั‚ะฐ ะฒ ะฝะฐัั‚ะพัั‰ะตะต ะฒั€ะตะผั ะฝะต ัะธะฝั…ั€ะพะฝะธะทะธั€ะพะฒะฐะฝะฐ."; "screen_chat_backup_recovery_action_setup" = "ะะฐัั‚ั€ะพะธั‚ัŒ ะฒะพััั‚ะฐะฝะพะฒะปะตะฝะธะต"; "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$@"; @@ -421,6 +459,17 @@ "screen_create_room_public_option_description" = "ะกะพะพะฑั‰ะตะฝะธั ะฝะต ะทะฐัˆะธั„ั€ะพะฒะฐะฝั‹, ะบะฐะถะดั‹ะน ะผะพะถะตั‚ ะธั… ะฟั€ะพั‡ะธั‚ะฐั‚ัŒ. ะ’ั‹ ะผะพะถะตั‚ะต ะฒะบะปัŽั‡ะธั‚ัŒ ัˆะธั„ั€ะพะฒะฐะฝะธะต ะฟะพะทะถะต."; "screen_create_room_public_option_title" = "ะŸัƒะฑะปะธั‡ะฝะฐั ะบะพะผะฝะฐั‚ะฐ (ะปัŽะฑะพะน)"; "screen_create_room_topic_label" = "ะขะตะผะฐ (ะฝะตะพะฑัะทะฐั‚ะตะปัŒะฝะพ)"; +"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" = "ะ’ะฐัˆะต ะพั‚ะพะฑั€ะฐะถะฐะตะผะพะต ะธะผั"; @@ -428,12 +477,20 @@ "screen_edit_profile_error_title" = "ะะตะฒะพะทะผะพะถะฝะพ ะพะฑะฝะพะฒะธั‚ัŒ ะฟั€ะพั„ะธะปัŒ"; "screen_edit_profile_title" = "ะ ะตะดะฐะบั‚ะธั€ะพะฒะฐั‚ัŒ ะฟั€ะพั„ะธะปัŒ"; "screen_edit_profile_updating_details" = "ะžะฑะฝะพะฒะปะตะฝะธะต ะฟั€ะพั„ะธะปัโ€ฆ"; +"screen_encryption_reset_action_continue_reset" = "ะŸั€ะพะดะพะปะถะธั‚ัŒ ัะฑั€ะพั"; +"screen_encryption_reset_bullet_1" = "ะ”ะฐะฝะฝั‹ะต ะฒะฐัˆะตะน ัƒั‡ะตั‚ะฝะพะน ะทะฐะฟะธัะธ, ะบะพะฝั‚ะฐะบั‚ั‹, ะฝะฐัั‚ั€ะพะนะบะธ ะธ ัะฟะธัะพะบ ั‡ะฐั‚ะพะฒ ะฑัƒะดัƒั‚ ัะพั…ั€ะฐะฝะตะฝั‹"; +"screen_encryption_reset_bullet_2" = "ะ’ั‹ ะฟะพั‚ะตั€ัะตั‚ะต ััƒั‰ะตัั‚ะฒัƒัŽั‰ัƒัŽ ะธัั‚ะพั€ะธัŽ ัะพะพะฑั‰ะตะฝะธะน"; +"screen_encryption_reset_bullet_3" = "ะ’ะฐะผ ะฝัƒะถะฝะพ ะฑัƒะดะตั‚ ะทะฐะฝะพะฒะพ ะฟะพะดั‚ะฒะตั€ะดะธั‚ัŒ ะฒัะต ััƒั‰ะตัั‚ะฒัƒัŽั‰ะธะต ัƒัั‚ั€ะพะนัั‚ะฒะฐ ะธ ะบะพะฝั‚ะฐะบั‚ั‹."; +"screen_encryption_reset_footer" = "ะกะฑั€ะฐัั‹ะฒะฐะนั‚ะต ะดะฐะฝะฝั‹ะต ั‚ะพะปัŒะบะพ ะฒ ั‚ะพะผ ัะปัƒั‡ะฐะต, ะตัะปะธ ัƒ ะฒะฐั ะฝะตั‚ ะดะพัั‚ัƒะฟะฐ ะบ ะดั€ัƒะณะพะผัƒ ัƒัั‚ั€ะพะนัั‚ะฒัƒ, ะฝะฐ ะบะพั‚ะพั€ะพะผ ะฒั‹ะฟะพะปะฝะตะฝ ะฒั…ะพะด, ะธ ะฒั‹ ะฟะพั‚ะตั€ัะปะธ ะบะปัŽั‡ ะฒะพััั‚ะฐะฝะพะฒะปะตะฝะธั."; +"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" = "ะ˜ัะฟะพะปัŒะทัƒะนั‚ะต ะดั€ัƒะณะพะต ัƒัั‚ั€ะพะนัั‚ะฒะพ"; +"screen_identity_confirmation_use_recovery_key" = "ะ˜ัะฟะพะปัŒะทัƒะนั‚ะต recovery key"; "screen_identity_confirmed_subtitle" = "ะขะตะฟะตั€ัŒ ะฒั‹ ะผะพะถะตั‚ะต ะฑะตะทะพะฟะฐัะฝะพ ั‡ะธั‚ะฐั‚ัŒ ะธ ะพั‚ะฟั€ะฐะฒะปัั‚ัŒ ัะพะพะฑั‰ะตะฝะธั, ะธ ะฒัะต, ั ะบะตะผ ะฒั‹ ะพะฑั‰ะฐะตั‚ะตััŒ ะฒ ั‡ะฐั‚ะต, ั‚ะฐะบะถะต ะผะพะณัƒั‚ ะดะพะฒะตั€ัั‚ัŒ ัั‚ะพะผัƒ ัƒัั‚ั€ะพะนัั‚ะฒัƒ."; "screen_identity_confirmed_title" = "ะฃัั‚ั€ะพะนัั‚ะฒะพ ะฟั€ะพะฒะตั€ะตะฝะพ"; -"screen_identity_use_another_device" = "ะ˜ัะฟะพะปัŒะทัƒะนั‚ะต ะดั€ัƒะณะพะต ัƒัั‚ั€ะพะนัั‚ะฒะพ"; "screen_identity_waiting_on_other_device" = "ะžะถะธะดะฐะฝะธะต ะฝะฐ ะดั€ัƒะณะพะผ ัƒัั‚ั€ะพะนัั‚ะฒะตโ€ฆ"; "screen_invites_decline_chat_message" = "ะ’ั‹ ัƒะฒะตั€ะตะฝั‹, ั‡ั‚ะพ ั…ะพั‚ะธั‚ะต ะพั‚ะบะปะพะฝะธั‚ัŒ ะฟั€ะธะณะปะฐัˆะตะฝะธะต ะฒ %1$@?"; "screen_invites_decline_chat_title" = "ะžั‚ะบะปะพะฝะธั‚ัŒ ะฟั€ะธะณะปะฐัˆะตะฝะธะต"; @@ -556,7 +613,6 @@ "screen_recovery_key_confirm_error_content" = "ะŸะพะถะฐะปัƒะนัั‚ะฐ, ะฟะพะฟั€ะพะฑัƒะนั‚ะต ะตั‰ะต ั€ะฐะท, ั‡ั‚ะพะฑั‹ ะฟะพะดั‚ะฒะตั€ะดะธั‚ัŒ ะดะพัั‚ัƒะฟ ะบ ั€ะตะทะตั€ะฒะฝะพะน ะบะพะฟะธะธ ั‡ะฐั‚ะฐ."; "screen_recovery_key_confirm_error_title" = "ะะตะฒะตั€ะฝั‹ะน ะบะปัŽั‡ ะฒะพััั‚ะฐะฝะพะฒะปะตะฝะธั"; "screen_recovery_key_confirm_key_description" = "ะ•ัะปะธ ัƒ ะฒะฐั ะตัั‚ัŒ ะฟะฐั€ะพะปัŒ ะดะปั ะฒะพััั‚ะฐะฝะพะฒะปะตะฝะธั ะธะปะธ ัะตะบั€ะตั‚ะฝั‹ะน ะฟะฐั€ะพะปัŒ/ะบะปัŽั‡, ัั‚ะพ ั‚ะพะถะต ัั€ะฐะฑะพั‚ะฐะตั‚."; -"screen_recovery_key_confirm_key_label" = "ะšะปัŽั‡ ะฒะพััั‚ะฐะฝะพะฒะปะตะฝะธั ะธะปะธ ะฟะฐั€ะพะปัŒ"; "screen_recovery_key_confirm_key_placeholder" = "ะ’ั…ะพะดโ€ฆ"; "screen_recovery_key_confirm_lost_recovery_key" = "ะŸะพั‚ะตั€ัะปะธ ะบะปัŽั‡ ะฒะพััั‚ะฐะฝะพะฒะปะตะฝะธั?"; "screen_recovery_key_confirm_success" = "ะšะปัŽั‡ ะฒะพััั‚ะฐะฝะพะฒะปะตะฝะธั ะฟะพะดั‚ะฒะตั€ะถะดะตะฝ"; @@ -577,6 +633,14 @@ "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_placeholder" = "ะ’ะฒะพะด..."; +"screen_reset_encryption_password_subtitle" = "ะŸะพะดั‚ะฒะตั€ะดะธั‚ะต, ั‡ั‚ะพ ะฒั‹ ั…ะพั‚ะธั‚ะต ัะฑั€ะพัะธั‚ัŒ ัˆะธั„ั€ะพะฒะฐะฝะธะต."; +"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_attachment_source_camera" = "ะšะฐะผะตั€ะฐ"; "screen_room_attachment_source_camera_video" = "ะ—ะฐะฟะธัะฐั‚ัŒ ะฒะธะดะตะพ"; @@ -775,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "ะ’ั‹ ัะพั…ั€ะฐะฝะธะปะธ ัะฒะพะน ะบะปัŽั‡ ะฒะพััั‚ะฐะฝะพะฒะปะตะฝะธั?"; "screen_start_chat_error_starting_chat" = "ะŸั€ะพะธะทะพัˆะปะฐ ะพัˆะธะฑะบะฐ ะฟั€ะธ ะฟะพะฟั‹ั‚ะบะต ะพั‚ะบั€ั‹ั‚ะธั ะบะพะผะฝะฐั‚ั‹"; "screen_view_location_title" = "ะœะตัั‚ะพะฟะพะปะพะถะตะฝะธะต"; -"screen_waitlist_message" = "ะ’ ะฝะฐัั‚ะพัั‰ะตะต ะฒั€ะตะผั ััƒั‰ะตัั‚ะฒัƒะตั‚ ะฒั‹ัะพะบะธะน ัะฟั€ะพั ะฝะฐ %1$@ ะฝะฐ %2$@. ะ’ะตั€ะฝะธั‚ะตััŒ ะฒ ะฟั€ะธะปะพะถะตะฝะธะต ั‡ะตั€ะตะท ะฝะตัะบะพะปัŒะบะพ ะดะฝะตะน ะธ ะฟะพะฟั€ะพะฑัƒะนั‚ะต ัะฝะพะฒะฐ.\n\nะกะฟะฐัะธะฑะพ ะทะฐ ั‚ะตั€ะฟะตะฝะธะต!"; -"screen_waitlist_title" = "ะŸะพั‡ั‚ะธ ะณะพั‚ะพะฒะพ."; -"screen_waitlist_title_success" = "ะ’ั‹ ะทะฐั€ะตะณะธัั‚ั€ะธั€ะพะฒะฐะฝั‹."; "screen_welcome_bullet_1" = "ะ—ะฒะพะฝะบะธ, ะพะฟั€ะพัั‹, ะฟะพะธัะบ ะธ ะผะฝะพะณะพะต ะดั€ัƒะณะพะต ะฑัƒะดัƒั‚ ะดะพะฑะฐะฒะปะตะฝั‹ ะฟะพะทะถะต ะฒ ัั‚ะพะผ ะณะพะดัƒ."; "screen_welcome_bullet_2" = "ะ˜ัั‚ะพั€ะธั ัะพะพะฑั‰ะตะฝะธะน ะดะปั ะทะฐัˆะธั„ั€ะพะฒะฐะฝะฝั‹ั… ะบะพะผะฝะฐั‚ ะฒ ัั‚ะพะผ ะพะฑะฝะพะฒะปะตะฝะธะธ ะฑัƒะดะตั‚ ะฝะตะดะพัั‚ัƒะฟะฝะฐ."; "screen_welcome_bullet_3" = "ะœั‹ ะฑัƒะดะตะผ ั€ะฐะดั‹ ัƒัะปั‹ัˆะฐั‚ัŒ ะฒะฐัˆะต ะผะฝะตะฝะธะต, ัะพะพะฑั‰ะธั‚ะต ะฝะฐะผ ะพะฑ ัั‚ะพะผ ั‡ะตั€ะตะท ัั‚ั€ะฐะฝะธั†ัƒ ะฝะฐัั‚ั€ะพะตะบ."; @@ -834,6 +895,12 @@ "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$@ ะธะทะผะตะฝะธะป ะทะฐะบั€ะตะฟะปะตะฝะฝั‹ะต ัะพะพะฑั‰ะตะฝะธั"; +"state_event_room_pinned_events_changed_by_you" = "ะ’ั‹ ะธะทะผะตะฝะธะปะธ ะทะฐะบั€ะตะฟะปะตะฝะฝั‹ะต ัะพะพะฑั‰ะตะฝะธั"; +"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_by_you" = "ะ’ั‹ ะพั‚ะบั€ะตะฟะธะปะธ ัะพะพะฑั‰ะตะฝะธะต"; "state_event_room_reject" = "%1$@ ะพั‚ะบะปะพะฝะธะป ะฟั€ะธะณะปะฐัˆะตะฝะธะต"; "state_event_room_reject_by_you" = "ะ’ั‹ ะพั‚ะบะปะพะฝะธะปะธ ะฟั€ะธะณะปะฐัˆะตะฝะธะต"; "state_event_room_remove" = "%1$@ ัƒะดะฐะปะธะป %2$@"; @@ -921,6 +988,7 @@ "screen_dm_details_unblock_user" = "ะ ะฐะทะฑะปะพะบะธั€ะพะฒะฐั‚ัŒ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั"; "screen_edit_poll_delete_confirmation_title" = "ะฃะดะฐะปะธั‚ัŒ ะพะฟั€ะพั"; "screen_edit_poll_title" = "ะ ะตะดะฐะบั‚ะธั€ะพะฒะฐั‚ัŒ ะพะฟั€ะพั"; +"screen_identity_use_another_device" = "ะ˜ัะฟะพะปัŒะทัƒะนั‚ะต ะดั€ัƒะณะพะต ัƒัั‚ั€ะพะนัั‚ะฒะพ"; "screen_login_subtitle" = "Matrix โ€” ัั‚ะพ ะพั‚ะบั€ั‹ั‚ะฐั ัะตั‚ัŒ ะดะปั ะฑะตะทะพะฟะฐัะฝะพะน ะดะตั†ะตะฝั‚ั€ะฐะปะธะทะพะฒะฐะฝะฝะพะน ัะฒัะทะธ."; "screen_qr_code_login_invalid_scan_state_retry_button" = "ะŸะพะฒั‚ะพั€ะธั‚ัŒ ะฟะพะฟั‹ั‚ะบัƒ"; "screen_report_content_block_user" = "ะ—ะฐะฑะปะพะบะธั€ะพะฒะฐั‚ัŒ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "ะ’ั‹ะนั‚ะธ"; "screen_signout_confirmation_dialog_title" = "ะ’ั‹ะนั‚ะธ"; "screen_signout_preference_item" = "ะ’ั‹ะนั‚ะธ"; -"screen_waitlist_message_success" = "ะ”ะพะฑั€ะพ ะฟะพะถะฐะปะพะฒะฐั‚ัŒ ะฒ %1$@!"; diff --git a/ElementX/Resources/Localizations/ru.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/ru.lproj/Localizable.stringsdict index 350bb3d562..2a5f2f2586 100644 --- a/ElementX/Resources/Localizations/ru.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/ru.lproj/Localizable.stringsdict @@ -218,6 +218,24 @@ ะะตะฒะตั€ะฝั‹ะน PIN-ะบะพะด. ะฃ ะฒะฐั ะพัั‚ะฐะปัั %1$d ัˆะฐะฝัะฐ + screen_pinned_timeline_screen_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d ะ—ะฐะบั€ะตะฟะปะตะฝะฝะพะต ัะพะพะฑั‰ะตะฝะธะต + few + %1$d ะ—ะฐะบั€ะตะฟะปะตะฝะฝั‹ั… ัะพะพะฑั‰ะตะฝะธะน + many + %1$d ะ—ะฐะบั€ะตะฟะปะตะฝะฝั‹ั… ัะพะพะฑั‰ะตะฝะธะน + + screen_room_member_list_header_title NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/sk.lproj/Localizable.strings b/ElementX/Resources/Localizations/sk.lproj/Localizable.strings index f7516d8bb4..dba24dba2a 100644 --- a/ElementX/Resources/Localizations/sk.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/sk.lproj/Localizable.strings @@ -27,17 +27,20 @@ "action_back" = "Spรคลฅ"; "action_call" = "Zavolaลฅ"; "action_cancel" = "Zruลกiลฅ"; +"action_cancel_for_now" = "Zatiaฤพ zruลกiลฅ"; "action_choose_photo" = "Vybraลฅ fotku"; "action_clear" = "Vyฤistiลฅ"; "action_close" = "Zavrieลฅ"; "action_complete_verification" = "Dokonฤiลฅ overenie"; "action_confirm" = "Potvrdiลฅ"; +"action_confirm_password" = "Potvrdiลฅ heslo"; "action_continue" = "Pokraฤovaลฅ"; "action_copy" = "Kopรญrovaลฅ"; "action_copy_link" = "Kopรญrovaลฅ odkaz"; "action_copy_link_to_message" = "Kopรญrovaลฅ odkaz do sprรกvy"; "action_create" = "Vytvoriลฅ"; "action_create_a_room" = "Vytvoriลฅ miestnosลฅ"; +"action_deactivate" = "Deaktivovaลฅ"; "action_decline" = "Odmietnuลฅ"; "action_delete_poll" = "Odstrรกniลฅ anketu"; "action_disable" = "Vypnรบลฅ"; @@ -70,6 +73,7 @@ "action_ok" = "OK"; "action_open_settings" = "Otvoriลฅ nastavenia"; "action_open_with" = "Otvoriลฅ pomocou"; +"action_pin" = "Pripnรบลฅ"; "action_quick_reply" = "Rรฝchla odpoveฤ"; "action_quote" = "Citovaลฅ"; "action_react" = "Reagovaลฅ"; @@ -80,6 +84,7 @@ "action_report_bug" = "Nahlรกsiลฅ chybu"; "action_report_content" = "Nahlรกsiลฅ obsah"; "action_reset" = "Obnoviลฅ"; +"action_reset_identity" = "Obnoviลฅ identitu"; "action_retry" = "Skรบsiลฅ znova"; "action_retry_decryption" = "Opakovaลฅ deลกifrovanie"; "action_save" = "Uloลพiลฅ"; @@ -99,10 +104,18 @@ "action_take_photo" = "Urobiลฅ fotku"; "action_tap_for_options" = "Klepnutรญm zรญskate moลพnosti"; "action_try_again" = "Skรบste to znova"; +"action_unpin" = "Odopnรบลฅ"; +"action_view_in_timeline" = "Zobraziลฅ na ฤasovej osi"; "action_view_source" = "Zobraziลฅ zdroj"; "action_yes" = "รno"; "action.load_more" = "Naฤรญtaลฅ viac"; -"action.pin" = "Pripnรบลฅ"; +"action_deactivate_account" = "Deaktivovaลฅ รบฤet"; +"banner_migrate_to_native_sliding_sync_action" = "Odhlรกsiลฅ sa a aktualizovaลฅ"; +"banner_migrate_to_native_sliding_sync_description" = "Vรกลก server teraz podporuje novรฝ, rรฝchlejลกรญ protokol. Odhlรกste sa a prihlรกste sa znova, aby ste mohli aktualizovaลฅ. Ak to urobรญte teraz, pomรดลพe vรกm vyhnรบลฅ sa nรบtenรฉmu odhlรกseniu, keฤ sa starรฝ protokol neskรดr odstrรกni."; +"banner_migrate_to_native_sliding_sync_force_logout_title" = "Vรกลก domovskรฝ server uลพ nepodporuje starรฝ protokol. Ak chcete pokraฤovaลฅ v pouลพรญvanรญ aplikรกcie, odhlรกste sa a znova sa prihlรกste."; +"banner_migrate_to_native_sliding_sync_title" = "Aktualizรกcia je k dispozรญcii"; +"banner.set_up_recovery.content" = "Vytvorte novรฝ kฤพรบฤ na obnovenie, ktorรฝ mรดลพete pouลพiลฅ na obnovenie vaลกej histรณrie ลกifrovanรฝch sprรกv v prรญpade straty prรญstupu k vaลกim zariadeniam."; +"banner.set_up_recovery.title" = "Nastaviลฅ obnovenie"; "common_about" = "O aplikรกcii"; "common_acceptable_use_policy" = "Zรกsady prijateฤพnรฉho pouลพรญvania"; "common_advanced_settings" = "Pokroฤilรฉ nastavenia"; @@ -214,6 +227,7 @@ "common_waiting_for_decryption_key" = "ฤŒakรก sa na deลกifrovacรญ kฤพรบฤ"; "common.do_not_show_this_again" = "Nezobrazovaลฅ toto znova"; "common.open_source_licenses" = "Licencie s otvorenรฝm zdrojom"; +"common.pinned" = "Pripnutรฉ"; "common.send_to" = "Odoslaลฅ"; "common_no_room_name" = "ลฝiadny nรกzov miestnosti"; "common_poll_end_confirmation" = "Ste si istรญ, ลพe chcete ukonฤiลฅ tรบto anketu?"; @@ -244,6 +258,7 @@ "emoji_picker_category_people" = "Smajlรญky a ฤพudia"; "emoji_picker_category_places" = "Cestovanie a miesta"; "emoji_picker_category_symbols" = "Symboly"; +"error_account_creation_not_possible" = "Vรกลก domovskรฝ server musรญ byลฅ aktualizovanรฝ tak, aby podporoval Matrix Authentication Service a vytvorenie รบฤtu."; "error_failed_creating_the_permalink" = "Nepodarilo sa vytvoriลฅ trvalรฝ odkaz"; "error_failed_loading_map" = "%1$@ nedokรกzal naฤรญtaลฅ mapu. Skรบste to prosรญm neskรดr."; "error_failed_loading_messages" = "Naฤรญtanie sprรกv zlyhalo"; @@ -254,6 +269,8 @@ "error_some_messages_have_not_been_sent" = "Niektorรฉ sprรกvy neboli odoslanรฉ"; "error_unknown" = "Prepรกฤte, vyskytla sa chyba"; "event_shield_reason_authenticity_not_guaranteed" = "Pravosลฅ tejto ลกifrovanej sprรกvy nie je moลพnรฉ zaruฤiลฅ na tomto zariadenรญ."; +"event_shield_reason_previously_verified" = "ล ifrovanรฉ predtรฝm overenรฝm pouลพรญvateฤพom."; +"event_shield_reason_sent_in_clear" = "Nie je ลกifrovanรฉ."; "event_shield_reason_unknown_device" = "Zaลกifrovanรฉ neznรกmym alebo odstrรกnenรฝm zariadenรญm."; "event_shield_reason_unsigned_device" = "ล ifrovanรฉ zariadenรญm, ktorรฉ nie je overenรฉ jeho majiteฤพom."; "event_shield_reason_unverified_identity" = "ล ifrovanรฉ neoverenรฝm pouลพรญvateฤพom."; @@ -275,11 +292,14 @@ "notification_inline_reply_failed" = "** Nepodarilo sa odoslaลฅ - prosรญm otvorte miestnosลฅ"; "notification_invitation_action_reject" = "Zamietnuลฅ"; "notification_invite_body" = "Vรกs pozval/a na konverzรกciu"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "notification_mentioned_you_body" = "Spomenul/a vรกs: %1$@"; "notification_new_messages" = "Novรฉ sprรกvy"; "notification_reaction_body" = "Reagoval/a s %1$@"; "notification_room_invite_body" = "Vรกs pozval do miestnosti"; +"notification_room_invite_body_with_sender" = "%1$@ invited you to join the room"; "notification_sender_me" = "Ja"; +"notification_sender_mention_reply" = "%1$@ spomenul/a alebo odpovedal/a"; "notification_test_push_notification_content" = "Prezerรกte si oznรกmenie! Kliknite na mลˆa!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -312,10 +332,27 @@ "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_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_pinned_timeline_screen_title_empty" = "Pripnutรฉ sprรกvy"; +"screen_reset_encryption_password_error" = "Nastala neznรกma chyba. Skontrolujte, ฤi je heslo vรกลกho รบฤtu sprรกvne a skรบste to znova."; +"screen_resolve_send_failure_changed_identity_primary_button_title" = "Odvolaลฅ overenie a odoslaลฅ"; +"screen_resolve_send_failure_changed_identity_subtitle" = "Svoje overenie mรดลพete odvolaลฅ a odoslaลฅ tรบto sprรกvu aj tak, alebo ju mรดลพete zatiaฤพ zruลกiลฅ a po opรคtovnom overenรญ to skรบsiลฅ znova %1$@ ."; +"screen_resolve_send_failure_changed_identity_title" = "Vaลกa sprรกva nebola odoslanรก, pretoลพe sa zmenila overenรก totoลพnosลฅ pouลพรญvateฤพa %1$@."; +"screen_resolve_send_failure_unsigned_device_primary_button_title" = "Odoslaลฅ sprรกvu aj tak"; +"screen_resolve_send_failure_unsigned_device_subtitle" = "%1$@ pouลพรญva jedno alebo viac neoverenรฝch zariadenรญ. Sprรกvu mรดลพete odoslaลฅ aj tak, alebo ju mรดลพete zatiaฤพ zruลกiลฅ a skรบsiลฅ to znova neskรดr po %2$@ overenรญ vลกetkรฝch zariadenรญ."; +"screen_resolve_send_failure_unsigned_device_title" = "Vaลกa sprรกva nebola odoslanรก, pretoลพe %1$@ neoveril/a vลกetky zariadenia."; +"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.pinned_banner_indicator" = "%1$@ z %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ Pripnutรฝch sprรกv"; -"screen.room.pinned_banner_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_details_pinned_events_row_title" = "Pripnutรฉ sprรกvy"; +"screen_timeline_item_menu_send_failure_changed_identity" = "Sprรกva nebola odoslanรก, pretoลพe sa zmenila overenรก totoลพnosลฅ pouลพรญvateฤพa %1$@."; +"screen_timeline_item_menu_send_failure_unsigned_device" = "Sprรกva nebola odoslanรก, pretoลพe %1$@ neoveril/a vลกetky zariadenia."; +"screen_timeline_item_menu_send_failure_you_unsigned_device" = "Sprรกva nebola odoslanรก, pretoลพe ste neoverili jedno alebo viac svojich zariadenรญ."; "screen_account_provider_change" = "Zmeniลฅ poskytovateฤพa รบฤtu"; "screen_account_provider_form_hint" = "Adresa domovskรฉho servera"; "screen_account_provider_form_notice" = "Zadajte hฤพadanรฝ vรฝraz alebo adresu domรฉny."; @@ -398,6 +435,7 @@ "screen_chat_backup_recovery_action_confirm_description" = "Vaลกa zรกloha konverzรกcie nie je momentรกlne synchronizovanรก."; "screen_chat_backup_recovery_action_setup" = "Nastaviลฅ obnovovanie"; "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"; "screen_create_new_recovery_key_list_item_2" = "Znova sa prihlรกste do svojho รบฤtu"; "screen_create_new_recovery_key_list_item_3" = "Keฤ sa zobrazรญ vรฝzva na overenie vรกลกho zariadenia, vyberte %1$@"; @@ -421,6 +459,17 @@ "screen_create_room_public_option_description" = "Sprรกvy nie sรบ ลกifrovanรฉ a mรดลพe si ich preฤรญtaลฅ ktokoฤพvek. ล ifrovanie mรดลพete zapnรบลฅ neskรดr."; "screen_create_room_public_option_title" = "Verejnรก miestnosลฅ (ktokoฤพvek)"; "screen_create_room_topic_label" = "Tรฉma (voliteฤพnรฉ)"; +"screen_deactivate_account_confirmation_dialog_content" = "Prosรญm potvrฤte, ลพe chcete deaktivovaลฅ svoj รบฤet. Tรบto akciu nie je moลพnรฉ vrรกtiลฅ spรคลฅ."; +"screen_deactivate_account_delete_all_messages" = "Vymazaลฅ vลกetky moje sprรกvy"; +"screen_deactivate_account_delete_all_messages_notice" = "Upozornenie: Budรบcim pouลพรญvateฤพom sa mรดลพu zobraziลฅ neรบplnรฉ konverzรกcie."; +"screen_deactivate_account_description" = "Deaktivรกcia vรกลกho รบฤtu znamenรก %1$@, ลพe:"; +"screen_deactivate_account_description_bold_part" = "nezvratnรฝ"; +"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" = "Natrvalo zakรกzaลฅ"; +"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" = "Vaลกe sprรกvy budรบ stรกle viditeฤพnรฉ pre registrovanรฝch pouลพรญvateฤพov, ale nebudรบ dostupnรฉ pre novรฝch alebo neregistrovanรฝch pouลพรญvateฤพov, ak sa ich rozhodnete odstrรกniลฅ."; +"screen_deactivate_account_title" = "Deaktivovaลฅ รบฤet"; "screen_edit_poll_delete_confirmation" = "Ste si istรฝ, ลพe chcete odstrรกniลฅ tรบto anketu?"; "screen_edit_profile_display_name" = "Zobrazovanรฉ meno"; "screen_edit_profile_display_name_placeholder" = "Vaลกe zobrazovanรฉ meno"; @@ -428,12 +477,20 @@ "screen_edit_profile_error_title" = "Nepodarilo sa aktualizovaลฅ profil"; "screen_edit_profile_title" = "Upraviลฅ profil"; "screen_edit_profile_updating_details" = "Aktualizรกcia profilu..."; +"screen_encryption_reset_action_continue_reset" = "Pokraฤovaลฅ v obnovovanรญ"; +"screen_encryption_reset_bullet_1" = "รšdaje o vaลกom รบฤte, kontakty, predvoฤพby a zoznam konverzรกciรญ budรบ zachovanรฉ"; +"screen_encryption_reset_bullet_2" = "Stratรญte svoju existujรบcu histรณriu sprรกv"; +"screen_encryption_reset_bullet_3" = "Budete musieลฅ znova overiลฅ vลกetky existujรบce zariadenia a kontakty"; +"screen_encryption_reset_footer" = "Obnovte svoju totoลพnosลฅ iba vtedy, ak nemรกte prรญstup k inรฉmu prihlรกsenรฉmu zariadeniu a stratili ste kฤพรบฤ na obnovenie."; +"screen_encryption_reset_title" = "Znovu nastavte svoju totoลพnosลฅ v prรญpade, ลพe ju nemรดลพete potvrdiลฅ inรฝm spรดsobom"; +"screen_identity_confirmation_cannot_confirm" = "Nemรดลพete potvrdiลฅ?"; "screen_identity_confirmation_create_new_recovery_key" = "Vytvoriลฅ novรฝ kฤพรบฤ na obnovenie"; "screen_identity_confirmation_subtitle" = "Ak chcete nastaviลฅ zabezpeฤenรฉ sprรกvy, overte toto zariadenie."; "screen_identity_confirmation_title" = "Potvrฤte, ลพe ste to vy"; +"screen_identity_confirmation_use_another_device" = "Pouลพite inรฉ zariadenie"; +"screen_identity_confirmation_use_recovery_key" = "Pouลพiลฅ kฤพรบฤ na obnovenie"; "screen_identity_confirmed_subtitle" = "Teraz mรดลพete bezpeฤne ฤรญtaลฅ alebo odosielaลฅ sprรกvy a tomuto zariadeniu mรดลพe dรดverovaลฅ aj ktokoฤพvek, s kรฝm konverzujete."; "screen_identity_confirmed_title" = "Zariadenie overenรฉ"; -"screen_identity_use_another_device" = "Pouลพiลฅ inรฉ zariadenie"; "screen_identity_waiting_on_other_device" = "ฤŒakรก sa na druhom zariadenรญ..."; "screen_invites_decline_chat_message" = "Naozaj chcete odmietnuลฅ pozvรกnku na pripojenie do %1$@?"; "screen_invites_decline_chat_title" = "Odmietnuลฅ pozvanie"; @@ -556,7 +613,6 @@ "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_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_label" = "Kฤพรบฤ na obnovenie alebo prรญstupovรฝ kรณd"; "screen_recovery_key_confirm_key_placeholder" = "Zadaลฅ..."; "screen_recovery_key_confirm_lost_recovery_key" = "Stratili ste kฤพรบฤ na obnovenie?"; "screen_recovery_key_confirm_success" = "Kฤพรบฤ na obnovu potvrdenรฝ"; @@ -577,6 +633,14 @@ "screen_report_content_block_user_hint" = "Oznaฤte, ฤi chcete skryลฅ vลกetky aktuรกlne a budรบce sprรกvy od tohto pouลพรญvateฤพa"; "screen_report_content_explanation" = "Tรกto sprรกva bude nahlรกsenรก sprรกvcovi vรกลกho domovskรฉho servera. Nebude mรดcลฅ preฤรญtaลฅ ลพiadne ลกifrovanรฉ sprรกvy."; "screen_report_content_hint" = "Dรดvod nahlรกsenia tohto obsahu"; +"screen_reset_encryption_confirmation_alert_action" = "รno, znovu nastaviลฅ teraz"; +"screen_reset_encryption_confirmation_alert_subtitle" = "Tento proces je nezvratnรฝ."; +"screen_reset_encryption_confirmation_alert_title" = "Naozaj chcete obnoviลฅ svoje ลกifrovanie?"; +"screen_reset_encryption_password_placeholder" = "Zadajte..."; +"screen_reset_encryption_password_subtitle" = "Potvrฤte, ลพe chcete obnoviลฅ svoje ลกifrovanie."; +"screen_reset_encryption_password_title" = "Ak chcete pokraฤovaลฅ, zadajte heslo รบฤtu"; +"screen_reset_identity_confirmation_subtitle" = "Chystรกte sa prejsลฅ na svoj %1$@ รบฤet, aby ste obnovili svoju identitu. Potom budete vrรกtenรญ spรคลฅ do aplikรกcie."; +"screen_reset_identity_confirmation_title" = "Neviete potvrdiลฅ? Prejdite do svojho รบฤtu a obnovte svoju identitu."; "screen_room_alias_resolver_resolve_alias_failure" = "Nepodarilo sa nรกjsลฅ alias miestnosti."; "screen_room_attachment_source_camera" = "Kamera"; "screen_room_attachment_source_camera_video" = "Nahraลฅ video"; @@ -775,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "Uloลพili ste si kฤพรบฤ na obnovenie?"; "screen_start_chat_error_starting_chat" = "Pri pokuse o spustenie konverzรกcie sa vyskytla chyba"; "screen_view_location_title" = "Poloha"; -"screen_waitlist_message" = "Momentรกlne je veฤพkรฝ dopyt po %1$@ na %2$@. Vrรกลฅte sa do aplikรกcie za pรกr dnรญ a skรบste to znova.\n\nฤŽakujeme za trpezlivosลฅ!"; -"screen_waitlist_title" = "Ste na ฤakanej listine!"; -"screen_waitlist_title_success" = "Ste dnu!"; "screen_welcome_bullet_1" = "Hovory, ankety, vyhฤพadรกvanie a ฤalลกie funkcie pribudnรบ neskรดr v tomto roku."; "screen_welcome_bullet_2" = "Histรณria sprรกv pre zaลกifrovanรฉ miestnosti nebude v tejto aktualizรกcii k dispozรญcii."; "screen_welcome_bullet_3" = "Radi by sme od vรกs poฤuli, dajte nรกm vedieลฅ, ฤo si myslรญte, prostrednรญctvom strรกnky nastavenรญ."; @@ -834,6 +895,12 @@ "state_event_room_name_removed_by_you" = "Odstrรกnili ste nรกzov miestnosti"; "state_event_room_none" = "%1$@ nevykonal/a ลพiadne zmeny"; "state_event_room_none_by_you" = "Nevykonali ste ลพiadne zmeny"; +"state_event_room_pinned_events_changed" = "%1$@ zmenil/a pripnutรฉ sprรกvy"; +"state_event_room_pinned_events_changed_by_you" = "Zmenili ste pripnutรฉ sprรกvy"; +"state_event_room_pinned_events_pinned" = "%1$@ pripol/la sprรกvu"; +"state_event_room_pinned_events_pinned_by_you" = "Pripli ste sprรกvu"; +"state_event_room_pinned_events_unpinned" = "%1$@ zruลกil/a pripnutie sprรกvy"; +"state_event_room_pinned_events_unpinned_by_you" = "Zruลกili ste pripnutie sprรกvy"; "state_event_room_reject" = "%1$@ odmietol/a pozvรกnku"; "state_event_room_reject_by_you" = "Odmietli ste pozvรกnku"; "state_event_room_remove" = "%1$@ odstrรกnil/a %2$@"; @@ -921,6 +988,7 @@ "screen_dm_details_unblock_user" = "Odblokovaลฅ pouลพรญvateฤพa"; "screen_edit_poll_delete_confirmation_title" = "Odstrรกniลฅ anketu"; "screen_edit_poll_title" = "Upraviลฅ anketu"; +"screen_identity_use_another_device" = "Pouลพite inรฉ zariadenie"; "screen_login_subtitle" = "Matrix je otvorenรก sieลฅ pre bezpeฤnรบ a decentralizovanรบ komunikรกciu."; "screen_qr_code_login_invalid_scan_state_retry_button" = "Skรบste to znova"; "screen_report_content_block_user" = "Zablokovaลฅ pouลพรญvateฤพa"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "Odhlรกsiลฅ sa"; "screen_signout_confirmation_dialog_title" = "Odhlรกsiลฅ sa"; "screen_signout_preference_item" = "Odhlรกsiลฅ sa"; -"screen_waitlist_message_success" = "Vitajte v %1$@!"; diff --git a/ElementX/Resources/Localizations/sk.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/sk.lproj/Localizable.stringsdict index 8d762ecfe8..acd716ce57 100644 --- a/ElementX/Resources/Localizations/sk.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/sk.lproj/Localizable.stringsdict @@ -218,6 +218,24 @@ Nesprรกvny PIN kรณd. Mรกte eลกte %1$d pokusov + screen_pinned_timeline_screen_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d pripnutรก sprรกva + few + %1$d pripnutรฉ sprรกvy + other + %1$d pripnutรฝch sprรกv + + screen_room_member_list_header_title NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/sv.lproj/Localizable.strings b/ElementX/Resources/Localizations/sv.lproj/Localizable.strings index 79e8bb83b8..db7a12b982 100644 --- a/ElementX/Resources/Localizations/sv.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/sv.lproj/Localizable.strings @@ -1,4 +1,4 @@ -"Notification" = "Notification"; +"Notification" = "notis"; "a11y_delete" = "Radera"; "a11y_hide_password" = "Dรถlj lรถsenord"; "a11y_jump_to_bottom" = "Hoppa till botten"; @@ -25,19 +25,22 @@ "action_accept" = "Godkรคnn"; "action_add_to_timeline" = "Lรคgg till i tidslinjen"; "action_back" = "Tillbaka"; -"action_call" = "Call"; +"action_call" = "Ring"; "action_cancel" = "Avbryt"; +"action_cancel_for_now" = "Cancel for now"; "action_choose_photo" = "Vรคlj bild"; "action_clear" = "Rensa"; "action_close" = "Stรคng"; "action_complete_verification" = "Slutfรถr verifiering"; "action_confirm" = "Bekrรคfta"; +"action_confirm_password" = "Confirm password"; "action_continue" = "Fortsรคtt"; "action_copy" = "Kopiera"; "action_copy_link" = "Kopiera lรคnk"; "action_copy_link_to_message" = "Kopiera lรคnk till meddelande"; "action_create" = "Skapa"; "action_create_a_room" = "Skapa ett rum"; +"action_deactivate" = "Deactivate"; "action_decline" = "Neka"; "action_delete_poll" = "Radera omrรถstning"; "action_disable" = "Inaktivera"; @@ -63,23 +66,25 @@ "action_leave_room" = "Lรคmna rum"; "action_manage_account" = "Hantera konto"; "action_manage_devices" = "Hantera enheter"; -"action_message" = "Message"; +"action_message" = "Meddela"; "action_next" = "Nรคsta"; "action_no" = "Nej"; "action_not_now" = "Inte nu"; "action_ok" = "OK"; "action_open_settings" = "Instรคllningar"; "action_open_with" = "ร–ppna med"; +"action_pin" = "Fรคst"; "action_quick_reply" = "Snabbsvar"; "action_quote" = "Citera"; "action_react" = "Reagera"; -"action_reject" = "Reject"; +"action_reject" = "Avvisa"; "action_remove" = "Ta bort"; "action_reply" = "Svara"; "action_reply_in_thread" = "Svara i trรฅd"; "action_report_bug" = "Rapportera bugg"; "action_report_content" = "Rapportera innehรฅll"; "action_reset" = "ร…terstรคll"; +"action_reset_identity" = "ร…terstรคll identitet"; "action_retry" = "Fรถrsรถk igen"; "action_retry_decryption" = "Fรถrsรถk att avkryptera igen"; "action_save" = "Spara"; @@ -99,10 +104,18 @@ "action_take_photo" = "Ta ett foto"; "action_tap_for_options" = "Tryck fรถr alternativ"; "action_try_again" = "Fรถrsรถk igen"; +"action_unpin" = "Frigรถr"; +"action_view_in_timeline" = "Visa i tidslinjen"; "action_view_source" = "Visa kรคllkod"; "action_yes" = "Ja"; "action.load_more" = "Ladda mer"; -"action.pin" = "Pin"; +"action_deactivate_account" = "Deactivate account"; +"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" = "Skapa en ny รฅterstรคllningsnyckel som kan anvรคndas fรถr att รฅterstรคlla din krypterade meddelandehistorik om du fรถrlorar รฅtkomst till dina enheter."; +"banner.set_up_recovery.title" = "Stรคll in รฅterstรคllning"; "common_about" = "Om"; "common_acceptable_use_policy" = "Policy fรถr godtagbar anvรคndning"; "common_advanced_settings" = "Avancerade instรคllningar"; @@ -112,7 +125,7 @@ "common_blocked_users" = "Blockerade anvรคndare"; "common_bubbles" = "Bubblor"; "common_call_invite" = "Samtal pรฅgรฅr (stรถds inte)"; -"common_call_started" = "Call started"; +"common_call_started" = "Samtal startat"; "common_chat_backup" = "Chattsรคkerhetskopia"; "common_copyright" = "Upphovsrรคtt"; "common_creating_room" = "Skapar rum โ€ฆ"; @@ -156,7 +169,7 @@ "common_people" = "Personer"; "common_permalink" = "Permalรคnk"; "common_permission" = "Behรถrighet"; -"common_please_wait" = "Please waitโ€ฆ"; +"common_please_wait" = "Vรคnligen vรคnta โ€ฆ"; "common_poll_total_votes" = "Totalt antal rรถster: %1$@"; "common_poll_undisclosed_text" = "Resultaten visas efter att omrรถstningen har avslutats"; "common_privacy_policy" = "Integritetspolicy"; @@ -212,14 +225,15 @@ "common_voice_message" = "Rรถstmeddelande"; "common_waiting" = "Vรคntar โ€ฆ"; "common_waiting_for_decryption_key" = "Vรคntar pรฅ detta meddelande"; -"common.do_not_show_this_again" = "Do not show this again"; -"common.open_source_licenses" = "Open source licenses"; -"common.send_to" = "Send to"; -"common_no_room_name" = "No room name"; +"common.do_not_show_this_again" = "Visa inte detta igen"; +"common.open_source_licenses" = "Licenser fรถr รถppen kรคllkod"; +"common.pinned" = "Fรคst"; +"common.send_to" = "Skicka till"; +"common_no_room_name" = "Inget rumsnamn"; "common_poll_end_confirmation" = "ร„r du sรคker pรฅ att du vill avsluta den hรคr omrรถstningen?"; "common_poll_summary" = "Omrรถstning: %1$@"; -"common_something_went_wrong" = "Something went wrong"; -"common_unable_to_decrypt_no_access" = "You don't have access to this message"; +"common_something_went_wrong" = "Nรฅgot gick fel"; +"common_unable_to_decrypt_no_access" = "Du har inte tillgรฅng till det hรคr meddelandet"; "common_verify_device" = "Verifiera enheten"; "confirm_recovery_key_banner_message" = "Din chattsรคkerhetskopia รคr fรถr nรคrvarande inte synkroniserad. Du mรฅste ange din รฅterstรคllningsnyckel fรถr att behรฅlla รฅtkomsten till din chattsรคkerhetskopia."; "confirm_recovery_key_banner_title" = "Ange din รฅterstรคllningsnyckel"; @@ -244,21 +258,24 @@ "emoji_picker_category_people" = "Smileys & personer"; "emoji_picker_category_places" = "Resor & platser"; "emoji_picker_category_symbols" = "Symboler"; +"error_account_creation_not_possible" = "Your homeserver needs to be upgraded to support Matrix Authentication Service and account creation."; "error_failed_creating_the_permalink" = "Misslyckades att skapa permalรคnken"; "error_failed_loading_map" = "%1$@ kunde inte ladda kartan. Vรคnligen fรถrsรถk igen senare."; "error_failed_loading_messages" = "Misslyckades att ladda meddelanden"; "error_failed_locating_user" = "%1$@ kunde inte komma รฅt din plats. Vรคnligen fรถrsรถk igen senare."; "error_failed_uploading_voice_message" = "Misslyckades med att ladda upp ditt rรถstmeddelande."; -"error_message_not_found" = "Message not found"; +"error_message_not_found" = "Meddelandet hittades inte"; "error_no_compatible_app_found" = "Ingen kompatibel app hittades fรถr att hantera den hรคr รฅtgรคrden."; "error_some_messages_have_not_been_sent" = "Vissa meddelanden har inte skickats"; "error_unknown" = "Tyvรคrr, ett fel uppstod"; -"event_shield_reason_authenticity_not_guaranteed" = "The authenticity of this encrypted message can't be guaranteed on this device."; -"event_shield_reason_unknown_device" = "Encrypted by an unknown or deleted device."; -"event_shield_reason_unsigned_device" = "Encrypted by a device not verified by its owner."; -"event_shield_reason_unverified_identity" = "Encrypted by an unverified user."; -"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_title" = "Enhance your call experience"; +"event_shield_reason_authenticity_not_guaranteed" = "Detta krypterade meddelandes รคkthet kan inte garanteras pรฅ den hรคr enheten."; +"event_shield_reason_previously_verified" = "Krypterat av en tidigare verifierad anvรคndare."; +"event_shield_reason_sent_in_clear" = "Inte krypterad."; +"event_shield_reason_unknown_device" = "Krypterad av en okรคnd eller raderad enhet."; +"event_shield_reason_unsigned_device" = "Krypterad av en enhet som inte verifierats av รคgaren."; +"event_shield_reason_unverified_identity" = "Krypterad av en overifierad anvรคndare."; +"full_screen_intent_banner_message" = "Fรถr att sรคkerstรคlla att du aldrig missar ett viktigt samtal, รคndra dina instรคllningar fรถr att tillรฅta helskรคrmsmeddelanden nรคr telefonen รคr lรฅst."; +"full_screen_intent_banner_title" = "Fรถrbรคttra din samtalsupplevelse"; "invite_friends_rich_title" = "๐Ÿ”๏ธ Hรคng med mig pรฅ %1$@"; "invite_friends_text" = "Hallรฅ, prata med mig pรฅ %1$@: %2$@"; "leave_conversation_alert_subtitle" = "ร„r du sรคker pรฅ att du vill lรคmna den hรคr konversationen? Den hรคr konversationen รคr inte offentlig och du kommer inte att kunna gรฅ med igen utan en inbjudan."; @@ -269,17 +286,20 @@ "notification_channel_call" = "Samtal"; "notification_channel_listening_for_events" = "Lyssnar efter hรคndelser"; "notification_channel_noisy" = "Hรถgljudda aviseringar"; -"notification_channel_ringing_calls" = "Ringing calls"; +"notification_channel_ringing_calls" = "Ringande samtal"; "notification_channel_silent" = "Tysta aviseringar"; -"notification_incoming_call" = "Incoming call"; +"notification_incoming_call" = "Inkommande samtal"; "notification_inline_reply_failed" = "** Misslyckades att skicka - vรคnligen รถppna rummet"; "notification_invitation_action_reject" = "Avvisa"; "notification_invite_body" = "Bjรถd in dig att chatta"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "notification_mentioned_you_body" = "Nรคmnde dig: %1$@"; "notification_new_messages" = "Nya meddelanden"; "notification_reaction_body" = "Reagerade med %1$@"; "notification_room_invite_body" = "Bjรถd in dig att gรฅ med i rummet"; +"notification_room_invite_body_with_sender" = "%1$@ invited you to join the room"; "notification_sender_me" = "Jag"; +"notification_sender_mention_reply" = "%1$@ nรคmnde eller svarade"; "notification_test_push_notification_content" = "Du tittar pรฅ aviseringen! Klicka pรฅ mig!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -312,10 +332,27 @@ "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_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_pinned_timeline_screen_title_empty" = "Fรคsta meddelanden"; +"screen_reset_encryption_password_error" = "Ett okรคnt fel intrรคffade. Kontrollera att ditt kontolรถsenord รคr korrekt och fรถrsรถk igen."; +"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" = "Meddela hela rummet"; -"screen.room.pinned_banner_indicator" = "%1$@ of %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ Pinned messages"; -"screen.room.pinned_banner_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_details_pinned_events_row_title" = "Fรคsta meddelanden"; +"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_account_provider_change" = "Byt kontoleverantรถr"; "screen_account_provider_form_hint" = "Hemserveradress"; "screen_account_provider_form_notice" = "Ange ett sรถkord eller en domรคnadress."; @@ -398,13 +435,14 @@ "screen_chat_backup_recovery_action_confirm_description" = "Din chattsรคkerhetskopia รคr fรถr nรคrvarande osynkroniserad."; "screen_chat_backup_recovery_action_setup" = "Stรคll in รฅterstรคllning"; "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_new_recovery_key_list_item_1" = "Open %1$@ in a desktop device"; -"screen_create_new_recovery_key_list_item_2" = "Sign into your account again"; -"screen_create_new_recovery_key_list_item_3" = "When asked to verify your device, select %1$@"; -"screen_create_new_recovery_key_list_item_3_reset_all" = "โ€œReset allโ€"; -"screen_create_new_recovery_key_list_item_4" = "Follow the instructions to create a new recovery key"; -"screen_create_new_recovery_key_list_item_5" = "Save your new recovery key in a password manager or encrypted note"; -"screen_create_new_recovery_key_title" = "Reset the encryption for your account using another device"; +"screen_create_account_title" = "Create account"; +"screen_create_new_recovery_key_list_item_1" = "ร–ppna %1$@ pรฅ en skrivbordsenhet"; +"screen_create_new_recovery_key_list_item_2" = "Logga in pรฅ ditt konto igen"; +"screen_create_new_recovery_key_list_item_3" = "Nรคr du ombeds att verifiera din enhet, vรคlj %1$@"; +"screen_create_new_recovery_key_list_item_3_reset_all" = "โ€ร…terstรคll allaโ€"; +"screen_create_new_recovery_key_list_item_4" = "Fรถlj anvisningarna fรถr att skapa en ny รฅterstรคllningsnyckel"; +"screen_create_new_recovery_key_list_item_5" = "Spara din nya รฅterstรคllningsnyckel i en lรถsenordshanterare eller krypterad anteckning"; +"screen_create_new_recovery_key_title" = "ร…terstรคll krypteringen fรถr ditt konto med en annan enhet"; "screen_create_poll_add_option_btn" = "Lรคgg till alternativ"; "screen_create_poll_anonymous_desc" = "Visa resultat fรถrst efter att omrรถstningen avslutats"; "screen_create_poll_anonymous_headline" = "Dรถlj rรถster"; @@ -421,6 +459,17 @@ "screen_create_room_public_option_description" = "Meddelanden รคr inte krypterade och vem som helst kan lรคsa dem. Du kan aktivera kryptering vid ett senare tillfรคlle."; "screen_create_room_public_option_title" = "Offentligt rum (vem som helst)"; "screen_create_room_topic_label" = "ร„mne (valfritt)"; +"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_edit_poll_delete_confirmation" = "ร„r du sรคker pรฅ att du vill radera den hรคr omrรถstningen?"; "screen_edit_profile_display_name" = "Visningsnamn"; "screen_edit_profile_display_name_placeholder" = "Ditt visningsnamn"; @@ -428,12 +477,20 @@ "screen_edit_profile_error_title" = "Kunde inte uppdatera profilen"; "screen_edit_profile_title" = "Redigera profil"; "screen_edit_profile_updating_details" = "Uppdaterar profil โ€ฆ"; +"screen_encryption_reset_action_continue_reset" = "Fortsรคtt รฅterstรคllning"; +"screen_encryption_reset_bullet_1" = "Dina kontouppgifter, kontakter, instรคllningar och chattlistor kommer bevaras"; +"screen_encryption_reset_bullet_2" = "Du kommer att fรถrlora din befintliga meddelandehistorik"; +"screen_encryption_reset_bullet_3" = "Du mรฅste verifiera alla dina befintliga enheter och kontakter igen"; +"screen_encryption_reset_footer" = "ร…terstรคll bara din identitet om du inte har tillgรฅng till en annan inloggad enhet och du har tappat bort din รฅterstรคllningsnyckel."; +"screen_encryption_reset_title" = "ร…terstรคll din identitet ifall du inte kan bekrรคfta pรฅ annat sรคtt"; +"screen_identity_confirmation_cannot_confirm" = "Kan du inte bekrรคfta?"; "screen_identity_confirmation_create_new_recovery_key" = "Skapa en ny รฅterstรคllningsnyckel"; "screen_identity_confirmation_subtitle" = "Verifiera den hรคr enheten fรถr att konfigurera sรคkra meddelanden."; "screen_identity_confirmation_title" = "Bekrรคfta att det รคr du"; +"screen_identity_confirmation_use_another_device" = "Anvรคnd en annan enhet"; +"screen_identity_confirmation_use_recovery_key" = "Anvรคnd รฅterstรคllningsnyckel"; "screen_identity_confirmed_subtitle" = "Nu kan du lรคsa eller skicka meddelanden sรคkert, och alla du chattar med kan ocksรฅ lita pรฅ den hรคr enheten."; "screen_identity_confirmed_title" = "Enhet verifierad"; -"screen_identity_use_another_device" = "Anvรคnd en annan enhet"; "screen_identity_waiting_on_other_device" = "Vรคntar pรฅ annan enhet โ€ฆ"; "screen_invites_decline_chat_message" = "ร„r du sรคker pรฅ att du vill tacka nej till inbjudan att gรฅ med%1$@?"; "screen_invites_decline_chat_title" = "Avbรถj inbjudan"; @@ -441,14 +498,14 @@ "screen_invites_decline_direct_chat_title" = "Avbรถj chatt"; "screen_invites_empty_list" = "Inga inbjudningar"; "screen_invites_invited_you" = "%1$@ (%2$@) bjรถd in dig"; -"screen_join_room_join_action" = "Join room"; -"screen_join_room_knock_action" = "Knock to join"; -"screen_join_room_space_not_supported_description" = "%1$@ does not support spaces yet. You can access spaces on web."; -"screen_join_room_space_not_supported_title" = "Spaces are not supported yet"; -"screen_join_room_subtitle_knock" = "Click the button below and a room administrator will be notified. Youโ€™ll be able to join the conversation once approved."; -"screen_join_room_subtitle_no_preview" = "You must be a member of this room to view the message history."; -"screen_join_room_title_knock" = "Want to join this room?"; -"screen_join_room_title_no_preview" = "Preview is not available"; +"screen_join_room_join_action" = "Gรฅ med i rummet"; +"screen_join_room_knock_action" = "Knacka fรถr att gรฅ med"; +"screen_join_room_space_not_supported_description" = "%1$@ stรถder inte utrymmen รคn. Du kan komma รฅt utrymmen pรฅ webben."; +"screen_join_room_space_not_supported_title" = "Utrymmen stรถds inte รคnnu"; +"screen_join_room_subtitle_knock" = "Klicka pรฅ knappen nedan sรฅ kommer en rumsadministratรถr att meddelas. Du kommer att kunna gรฅ med i konversationen nรคr den har godkรคnts."; +"screen_join_room_subtitle_no_preview" = "Du mรฅste vara medlem i det hรคr rummet fรถr att se meddelandehistoriken."; +"screen_join_room_title_knock" = "Vill du gรฅ med i det hรคr rummet?"; +"screen_join_room_title_no_preview" = "Fรถrhandsgranskning รคr inte tillgรคnglig"; "screen_key_backup_disable_confirmation_action_turn_off" = "Stรคng av"; "screen_key_backup_disable_confirmation_description" = "Du kommer att fรถrlora dina krypterade meddelanden om du loggas ut frรฅn alla enheter."; "screen_key_backup_disable_confirmation_title" = "ร„r du sรคker pรฅ att du vill stรคnga av sรคkerhetskopiering?"; @@ -507,58 +564,57 @@ "screen_polls_history_filter_ongoing" = "Pรฅgรฅende"; "screen_polls_history_filter_past" = "Tidigare"; "screen_polls_history_title" = "Omrรถstningar"; -"screen_qr_code_login_connecting_subtitle" = "Establishing a secure connection"; -"screen_qr_code_login_connection_note_secure_state_description" = "A secure connection could not be made to the new device. Your existing devices are still safe and you don't need to worry about them."; -"screen_qr_code_login_connection_note_secure_state_list_header" = "What now?"; -"screen_qr_code_login_connection_note_secure_state_list_item_1" = "Try signing in again with a QR code in case this was a network problem"; -"screen_qr_code_login_connection_note_secure_state_list_item_2" = "If you encounter the same problem, try a different wifi network or use your mobile data instead of wifi"; -"screen_qr_code_login_connection_note_secure_state_list_item_3" = "If that doesnโ€™t work, sign in manually"; -"screen_qr_code_login_connection_note_secure_state_title" = "Connection not secure"; -"screen_qr_code_login_device_code_subtitle" = "Youโ€™ll be asked to enter the two digits shown on this device."; -"screen_qr_code_login_device_code_title" = "Enter the number below on your other device"; -"screen_qr_code_login_device_not_signed_in_scan_state_description" = "Sign in to your other device and then try again, or use another device thatโ€™s already signed in."; -"screen_qr_code_login_device_not_signed_in_scan_state_subtitle" = "Other device not signed in"; -"screen_qr_code_login_error_cancelled_subtitle" = "The sign in was cancelled on the other device."; -"screen_qr_code_login_error_cancelled_title" = "Sign in request cancelled"; -"screen_qr_code_login_error_declined_subtitle" = "The sign in was declined on the other device."; -"screen_qr_code_login_error_declined_title" = "Sign in declined"; -"screen_qr_code_login_error_expired_subtitle" = "Sign in expired. Please try again."; -"screen_qr_code_login_error_expired_title" = "The sign in was not completed in time"; -"screen_qr_code_login_error_linking_not_suported_subtitle" = "Your other device does not support signing in to %@ with a QR code.\n\nTry signing in manually, or scan the QR code with another device."; -"screen_qr_code_login_error_linking_not_suported_title" = "QR code not supported"; -"screen_qr_code_login_error_sliding_sync_not_supported_subtitle" = "Your account provider does not support %1$@."; -"screen_qr_code_login_error_sliding_sync_not_supported_title" = "%1$@ not supported"; -"screen_qr_code_login_initial_state_button_title" = "Ready to scan"; -"screen_qr_code_login_initial_state_item_1" = "Open %1$@ on a desktop device"; -"screen_qr_code_login_initial_state_item_2" = "Click on your avatar"; -"screen_qr_code_login_initial_state_item_3" = "Select %1$@"; -"screen_qr_code_login_initial_state_item_3_action" = "โ€œLink new deviceโ€"; -"screen_qr_code_login_initial_state_item_4" = "Scan the QR code with this device"; -"screen_qr_code_login_initial_state_title" = "Open %1$@ on another device to get the QR code"; -"screen_qr_code_login_invalid_scan_state_description" = "Use the QR code shown on the other device."; -"screen_qr_code_login_invalid_scan_state_subtitle" = "Wrong QR code"; -"screen_qr_code_login_no_camera_permission_button" = "Go to camera settings"; -"screen_qr_code_login_no_camera_permission_state_description" = "You need to give permission for %1$@ to use your deviceโ€™s camera in order to continue."; -"screen_qr_code_login_no_camera_permission_state_title" = "Allow camera access to scan the QR code"; -"screen_qr_code_login_scanning_state_title" = "Scan the QR code"; -"screen_qr_code_login_start_over_button" = "Start over"; -"screen_qr_code_login_unknown_error_description" = "An unexpected error occurred. Please try again."; -"screen_qr_code_login_verify_code_loading" = "Waiting for your other device"; -"screen_qr_code_login_verify_code_subtitle" = "Your account provider may ask for the following code to verify the sign in."; -"screen_qr_code_login_verify_code_title" = "Your verification code"; +"screen_qr_code_login_connecting_subtitle" = "Upprรคttar en sรคker anslutning"; +"screen_qr_code_login_connection_note_secure_state_description" = "En sรคker anslutning kunde inte gรถras till den nya enheten. Dina befintliga enheter รคr fortfarande sรคkra och du behรถver inte oroa dig fรถr dem."; +"screen_qr_code_login_connection_note_secure_state_list_header" = "Nu dรฅ?"; +"screen_qr_code_login_connection_note_secure_state_list_item_1" = "Prรถva att logga in igen med en QR-kod ifall detta skulle vara ett nรคtverksproblem"; +"screen_qr_code_login_connection_note_secure_state_list_item_2" = "Om du stรถter pรฅ samma problem, prova ett annat wifi-nรคtverk eller anvรคnd din mobildata istรคllet fรถr wifi"; +"screen_qr_code_login_connection_note_secure_state_list_item_3" = "Om det inte fungerar, logga in manuellt"; +"screen_qr_code_login_connection_note_secure_state_title" = "Anslutningen รคr inte sรคker"; +"screen_qr_code_login_device_code_subtitle" = "Du kommer att bli ombedd att ange de tvรฅ siffrorna som visas pรฅ den hรคr enheten."; +"screen_qr_code_login_device_code_title" = "Ange numret nedan pรฅ din andra enhet"; +"screen_qr_code_login_device_not_signed_in_scan_state_description" = "Logga in pรฅ din andra enhet och fรถrsรถk sedan igen, eller anvรคnd en annan enhet som redan รคr inloggad."; +"screen_qr_code_login_device_not_signed_in_scan_state_subtitle" = "Den andra enheten รคr inte inloggad"; +"screen_qr_code_login_error_cancelled_subtitle" = "Inloggningen avbrรถts pรฅ den andra enheten."; +"screen_qr_code_login_error_cancelled_title" = "Inloggningsfรถrfrรฅgan avbrรถts"; +"screen_qr_code_login_error_declined_subtitle" = "Inloggningen avvisades pรฅ den andra enheten."; +"screen_qr_code_login_error_declined_title" = "Inloggning avvisad"; +"screen_qr_code_login_error_expired_subtitle" = "Inloggningen har lรถpt ut. Vรคnligen fรถrsรถk igen."; +"screen_qr_code_login_error_expired_title" = "Inloggningen slutfรถrdes inte i tid"; +"screen_qr_code_login_error_linking_not_suported_subtitle" = "Din andra enhet stรถder inte inloggning i %@ med en QR-kod.\n\nProva att logga in manuellt eller skanna QR-koden med en annan enhet."; +"screen_qr_code_login_error_linking_not_suported_title" = "QR-kod stรถds inte"; +"screen_qr_code_login_error_sliding_sync_not_supported_subtitle" = "Din kontoleverantรถr stรถder inte %1$@."; +"screen_qr_code_login_error_sliding_sync_not_supported_title" = "%1$@ stรถds inte"; +"screen_qr_code_login_initial_state_button_title" = "Redo att skanna"; +"screen_qr_code_login_initial_state_item_1" = "ร–ppna %1$@ pรฅ en skrivbordsenhet"; +"screen_qr_code_login_initial_state_item_2" = "Klicka pรฅ din avatar"; +"screen_qr_code_login_initial_state_item_3" = "Vรคlj %1$@"; +"screen_qr_code_login_initial_state_item_3_action" = "โ€Lรคnka ny enhetโ€"; +"screen_qr_code_login_initial_state_item_4" = "Skanna QR-koden med den hรคr enheten"; +"screen_qr_code_login_initial_state_title" = "ร–ppna %1$@ pรฅ en annan enhet fรถr att fรฅ QR-koden"; +"screen_qr_code_login_invalid_scan_state_description" = "Anvรคnd QR-koden som visas pรฅ den andra enheten."; +"screen_qr_code_login_invalid_scan_state_subtitle" = "Fel QR-kod"; +"screen_qr_code_login_no_camera_permission_button" = "Gรฅ till kamerainstรคllningar"; +"screen_qr_code_login_no_camera_permission_state_description" = "Du mรฅste ge tillstรฅnd fรถr %1$@ att anvรคnda enhetens kamera fรถr att kunna fortsรคtta."; +"screen_qr_code_login_no_camera_permission_state_title" = "Tillรฅt kameraรฅtkomst fรถr att skanna QR-koden"; +"screen_qr_code_login_scanning_state_title" = "Skanna QR-koden"; +"screen_qr_code_login_start_over_button" = "Bรถrja om"; +"screen_qr_code_login_unknown_error_description" = "Ett ovรคntat fel intrรคffade. Vรคnligen fรถrsรถk igen."; +"screen_qr_code_login_verify_code_loading" = "Vรคntar pรฅ din andra enhet"; +"screen_qr_code_login_verify_code_subtitle" = "Din kontoleverantรถr kan be om fรถljande kod fรถr att verifiera inloggningen."; +"screen_qr_code_login_verify_code_title" = "Din verifieringskod"; "screen_recovery_key_change_description" = "Fรฅ en ny รฅterstรคllningsnyckel om du har tappat bort din befintliga. Nรคr du har bytt din รฅterstรคllningsnyckel fungerar din gamla inte lรคngre."; "screen_recovery_key_change_generate_key" = "Generera en ny รฅterstรคllningsnyckel"; "screen_recovery_key_change_generate_key_description" = "Se till att du kan lagra din รฅterstรคllningsnyckel nรฅgonstans sรคkert"; "screen_recovery_key_change_success" = "ร…terstรคllningsnyckel รคndrad"; "screen_recovery_key_change_title" = "Byt รฅterstรคllningsnyckel?"; -"screen_recovery_key_confirm_create_new_recovery_key" = "Create new recovery key"; +"screen_recovery_key_confirm_create_new_recovery_key" = "Skapa ny รฅterstรคllningsnyckel"; "screen_recovery_key_confirm_description" = "Se till att ingen kan se den hรคr skรคrmen"; "screen_recovery_key_confirm_error_content" = "Vรคnligen prรถva igen fรถr att bekrรคfta รฅtkomsten till din chattsรคkerhetskopia."; "screen_recovery_key_confirm_error_title" = "Felaktig รฅterstรคllningsnyckel"; "screen_recovery_key_confirm_key_description" = "Om du har en sรคkerhetsnyckel eller sรคkerhetsfras sรฅ funkar den ocksรฅ."; -"screen_recovery_key_confirm_key_label" = "Recovery key or passcode"; "screen_recovery_key_confirm_key_placeholder" = "Ange โ€ฆ"; -"screen_recovery_key_confirm_lost_recovery_key" = "Lost your recovery key?"; +"screen_recovery_key_confirm_lost_recovery_key" = "Blivit av med din รฅterstรคllningsnyckel?"; "screen_recovery_key_confirm_success" = "ร…terstรคllningsnyckel bekrรคftad"; "screen_recovery_key_confirm_title" = "Ange din รฅterstรคllningsnyckel"; "screen_recovery_key_copied_to_clipboard" = "Kopierade รฅterstรคllningsnyckel"; @@ -577,7 +633,15 @@ "screen_report_content_block_user_hint" = "Markera om du vill dรถlja alla nuvarande och framtida meddelanden frรฅn denna anvรคndare"; "screen_report_content_explanation" = "Det hรคr meddelandet kommer att rapporteras till din hemservers administratรถr. Denne kommer inte att kunna lรคsa nรฅgra krypterade meddelanden."; "screen_report_content_hint" = "Anledning till att rapportera detta innehรฅll"; -"screen_room_alias_resolver_resolve_alias_failure" = "Failed to resolve room alias."; +"screen_reset_encryption_confirmation_alert_action" = "Ja, รฅterstรคll nu"; +"screen_reset_encryption_confirmation_alert_subtitle" = "Denna process รคr irreversibel."; +"screen_reset_encryption_confirmation_alert_title" = "ร„r du sรคker pรฅ att du vill รฅterstรคlla din kryptering?"; +"screen_reset_encryption_password_placeholder" = "Ange โ€ฆ"; +"screen_reset_encryption_password_subtitle" = "Bekrรคfta att du vill รฅterstรคlla din kryptering."; +"screen_reset_encryption_password_title" = "Ange ditt kontolรถsenord fรถr att fortsรคtta"; +"screen_reset_identity_confirmation_subtitle" = "Du รคr pรฅ vรคg att gรฅ till ditt %1$@-konto fรถr att รฅterstรคlla din identitet. Dรคrefter kommer du att tas tillbaka till appen."; +"screen_reset_identity_confirmation_title" = "Kan du inte bekrรคfta? Gรฅ till ditt konto fรถr att รฅterstรคlla din identitet."; +"screen_room_alias_resolver_resolve_alias_failure" = "Misslyckades med att slรฅ upp rumsalias."; "screen_room_attachment_source_camera" = "Kamera"; "screen_room_attachment_source_camera_video" = "Spela in video"; "screen_room_attachment_source_files" = "Bilaga"; @@ -602,16 +666,16 @@ "screen_room_change_role_confirm_demote_self_description" = "Du kommer inte att kunna รฅngra denna รคndring eftersom du degraderar dig sjรคlv, om du รคr den sista privilegierade anvรคndaren i rummet kommer det att vara omรถjligt att รฅterfรฅ privilegier."; "screen_room_change_role_confirm_demote_self_title" = "Degradera dig sjรคlv?"; "screen_room_change_role_invited_member_name" = "%1$@ (Vรคntar)"; -"screen_room_change_role_moderators_admin_section_footer" = "Admins automatically have moderator privileges"; +"screen_room_change_role_moderators_admin_section_footer" = "Administratรถrer har automatiskt moderatorbehรถrighet"; "screen_room_change_role_moderators_title" = "Redigera moderatorer"; "screen_room_change_role_unsaved_changes_description" = "Du har osparade รคndringar."; "screen_room_change_role_unsaved_changes_title" = "Spara รคndringar?"; "screen_room_details_add_topic_title" = "Lรคgg till รคmne"; "screen_room_details_already_a_member" = "Redan medlem"; "screen_room_details_already_invited" = "Redan inbjuden"; -"screen_room_details_badge_encrypted" = "Encrypted"; -"screen_room_details_badge_not_encrypted" = "Not encrypted"; -"screen_room_details_badge_public" = "Public room"; +"screen_room_details_badge_encrypted" = "Krypterat"; +"screen_room_details_badge_not_encrypted" = "Inte krypterat"; +"screen_room_details_badge_public" = "Offentligt rum"; "screen_room_details_edit_room_title" = "Redigera rummet"; "screen_room_details_edition_error" = "Ett okรคnt fel uppstod och informationen kunde inte รคndras."; "screen_room_details_edition_error_title" = "Kunde inte uppdatera rummet"; @@ -700,7 +764,7 @@ "screen_room_timeline_reactions_show_less" = "Visa mindre"; "screen_room_timeline_reactions_show_more" = "Visa mer"; "screen_room_timeline_read_marker_title" = "Nytt"; -"screen_room_title" = "Chat"; +"screen_room_title" = "Chatt"; "screen_room_typing_many_members_first_component_ios" = "%1$@, %2$@ och "; "screen_room_typing_notification_plural_ios" = " skriver โ€ฆ"; "screen_room_typing_notification_singular_ios" = " skriver โ€ฆ"; @@ -712,8 +776,8 @@ "screen_roomlist_filter_favourites" = "Favoriter"; "screen_roomlist_filter_favourites_empty_state_subtitle" = "Du kan lรคgga till en chatt till dina favoriter i chattinstรคllningarna.\nFรถr tillfรคllet kan du avmarkera filter fรถr att se dina andra chattar"; "screen_roomlist_filter_favourites_empty_state_title" = "Du har inga favoritchattar รคn"; -"screen_roomlist_filter_invites" = "Invites"; -"screen_roomlist_filter_invites_empty_state_title" = "You don't have any pending invites."; +"screen_roomlist_filter_invites" = "Inbjudningar"; +"screen_roomlist_filter_invites_empty_state_title" = "Du har inga vรคntande inbjudningar."; "screen_roomlist_filter_low_priority" = "Lรฅg prioritet"; "screen_roomlist_filter_mixed_empty_state_subtitle" = "Du kan avmarkera filter fรถr att se dina andra chattar"; "screen_roomlist_filter_mixed_empty_state_title" = "Du har inga chattar fรถr det hรคr valet"; @@ -775,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "Har du sparat din รฅterstรคllningsnyckel?"; "screen_start_chat_error_starting_chat" = "Ett fel uppstod nรคr du fรถrsรถkte starta en chatt"; "screen_view_location_title" = "Plats"; -"screen_waitlist_message" = "Det finns en stor efterfrรฅgan pรฅ %1$@ pรฅ %2$@ just nu. Kom tillbaka till appen om nรฅgra dagar och fรถrsรถk igen.\n\nTack fรถr ditt tรฅlamod!"; -"screen_waitlist_title" = "Du รคr nรคstan framme."; -"screen_waitlist_title_success" = "Du รคr inne."; "screen_welcome_bullet_1" = "Samtal, omrรถstningar, sรถkning och mer kommer att lรคggas till senare i รฅr."; "screen_welcome_bullet_2" = "Meddelandehistorik fรถr krypterade rum รคr inte tillgรคnglig รคn."; "screen_welcome_bullet_3" = "Vi vill gรคrna hรถra frรฅn dig, lรฅt oss veta vad du tycker via instรคllningssidan."; @@ -834,6 +895,12 @@ "state_event_room_name_removed_by_you" = "Du tog bort rummets namn"; "state_event_room_none" = "%1$@ gjorde inga รคndringar"; "state_event_room_none_by_you" = "Du gjorde inga รคndringar"; +"state_event_room_pinned_events_changed" = "%1$@ รคndrade de fรคsta meddelandena"; +"state_event_room_pinned_events_changed_by_you" = "Du รคndrade de fรคsta meddelandena"; +"state_event_room_pinned_events_pinned" = "%1$@ fรคste ett meddelande"; +"state_event_room_pinned_events_pinned_by_you" = "Du har fรคste ett meddelande"; +"state_event_room_pinned_events_unpinned" = "%1$@ lossade ett meddelande"; +"state_event_room_pinned_events_unpinned_by_you" = "Du har lossade ett meddelande"; "state_event_room_reject" = "%1$@ avvisade inbjudan"; "state_event_room_reject_by_you" = "Du avvisade inbjudan"; "state_event_room_remove" = "%1$@ tog bort %2$@"; @@ -896,7 +963,7 @@ "troubleshoot_notifications_test_unified_push_title" = "Kontrollera UnifiedPush"; "dialog_title_error" = "Fel"; "dialog_title_success" = "Lyckades"; -"notification_fallback_content" = "Notification"; +"notification_fallback_content" = "notis"; "notification_invitation_action_join" = "Gรฅ med"; "notification_room_action_mark_as_read" = "Markera som lรคst"; "notification_room_action_quick_reply" = "Snabbsvar"; @@ -921,6 +988,7 @@ "screen_dm_details_unblock_user" = "Avblockera anvรคndare"; "screen_edit_poll_delete_confirmation_title" = "Radera omrรถstning"; "screen_edit_poll_title" = "Redigera omrรถstning"; +"screen_identity_use_another_device" = "Anvรคnd en annan enhet"; "screen_login_subtitle" = "Matrix รคr ett รถppet nรคtverk fรถr sรคker, decentraliserad kommunikation."; "screen_qr_code_login_invalid_scan_state_retry_button" = "Fรถrsรถk igen"; "screen_report_content_block_user" = "Blockera anvรคndare"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "Logga ut"; "screen_signout_confirmation_dialog_title" = "Logga ut"; "screen_signout_preference_item" = "Logga ut"; -"screen_waitlist_message_success" = "Vรคlkommen till %1$@!"; diff --git a/ElementX/Resources/Localizations/sv.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/sv.lproj/Localizable.stringsdict index 53d55db9f2..fe8c8bdc09 100644 --- a/ElementX/Resources/Localizations/sv.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/sv.lproj/Localizable.stringsdict @@ -194,6 +194,22 @@ Fel PIN-kod. Du har %1$d fรถrsรถk kvar + screen_pinned_timeline_screen_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d Fรคst meddelande + other + %1$d Fรคsta meddelanden + + screen_room_member_list_header_title NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/uk.lproj/Localizable.strings b/ElementX/Resources/Localizations/uk.lproj/Localizable.strings index c0db58a145..d0dad527bb 100644 --- a/ElementX/Resources/Localizations/uk.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/uk.lproj/Localizable.strings @@ -25,19 +25,22 @@ "action_accept" = "ะŸั€ะธะนะฝัั‚ะธ"; "action_add_to_timeline" = "ะ”ะพะดะฐั‚ะธ ะดะพ ัั‚ั€ั–ั‡ะบะธ"; "action_back" = "ะะฐะทะฐะด"; -"action_call" = "Call"; +"action_call" = "ะ—ะฐั‚ะตะปะตั„ะพะฝัƒะฒะฐั‚ะธ"; "action_cancel" = "ะกะบะฐััƒะฒะฐั‚ะธ"; +"action_cancel_for_now" = "Cancel for now"; "action_choose_photo" = "ะ’ะธะฑั€ะฐั‚ะธ ั„ะพั‚ะพ"; "action_clear" = "ะžั‡ะธัั‚ะธั‚ะธ"; "action_close" = "ะ—ะฐะบั€ะธั‚ะธ"; "action_complete_verification" = "ะ’ะตั€ะธั„ั–ะบะฐั†ั–ั ะทะฐะฒะตั€ัˆะตะฝะฐ"; "action_confirm" = "ะŸั–ะดั‚ะฒะตั€ะดะธั‚ะธ"; +"action_confirm_password" = "Confirm password"; "action_continue" = "ะŸั€ะพะดะพะฒะถะธั‚ะธ"; "action_copy" = "ะกะบะพะฟั–ัŽะฒะฐั‚ะธ"; "action_copy_link" = "ะกะบะพะฟั–ัŽะฒะฐั‚ะธ ะฟะพัะธะปะฐะฝะฝั"; "action_copy_link_to_message" = "ะกะบะพะฟั–ัŽะฒะฐั‚ะธ ะฟะพัะธะปะฐะฝะฝั ะฝะฐ ะฟะพะฒั–ะดะพะผะปะตะฝะฝั"; "action_create" = "ะกั‚ะฒะพั€ะธั‚ะธ"; "action_create_a_room" = "ะกั‚ะฒะพั€ะธั‚ะธ ะบั–ะผะฝะฐั‚ัƒ"; +"action_deactivate" = "Deactivate"; "action_decline" = "ะ’ั–ะดั…ะธะปะธั‚ะธ"; "action_delete_poll" = "ะ’ะธะดะฐะปะธั‚ะธ ะพะฟะธั‚ัƒะฒะฐะฝะฝั"; "action_disable" = "ะ’ะธะผะบะฝัƒั‚ะธ"; @@ -63,23 +66,25 @@ "action_leave_room" = "ะ’ะธะนั‚ะธ ะท ะบั–ะผะฝะฐั‚ะธ"; "action_manage_account" = "ะšะตั€ัƒะฒะฐะฝะฝั ะพะฑะปั–ะบะพะฒะธะผ ะทะฐะฟะธัะพะผ"; "action_manage_devices" = "ะšะตั€ัƒะฒะฐะฝะฝั ะฟั€ะธัั‚ั€ะพัะผะธ"; -"action_message" = "Message"; +"action_message" = "ะะฐะฟะธัะฐั‚ะธ"; "action_next" = "ะ”ะฐะปั–"; "action_no" = "ะั–"; "action_not_now" = "ะะต ะทะฐั€ะฐะท"; "action_ok" = "ะ“ะฐั€ะฐะทะด"; "action_open_settings" = "ะะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั"; "action_open_with" = "ะ’ั–ะดะบั€ะธั‚ะธ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ"; +"action_pin" = "ะ—ะฐะบั€ั–ะฟะธั‚ะธ"; "action_quick_reply" = "ะจะฒะธะดะบะฐ ะฒั–ะดะฟะพะฒั–ะดัŒ"; "action_quote" = "ะฆะธั‚ัƒะฒะฐั‚ะธ"; "action_react" = "ะ ะตะฐะบั†ั–ั"; -"action_reject" = "Reject"; +"action_reject" = "ะ’ั–ะดั…ะธะปะธั‚ะธ"; "action_remove" = "ะ’ะธะปัƒั‡ะธั‚ะธ"; "action_reply" = "ะ’ั–ะดะฟะพะฒั–ัั‚ะธ"; "action_reply_in_thread" = "ะ’ั–ะดะฟะพะฒั–ัั‚ะธ ะฒ ะณั–ะปั†ั–"; "action_report_bug" = "ะŸะพะฒั–ะดะพะผะธั‚ะธ ะฟั€ะพ ะฟะพะผะธะปะบัƒ"; "action_report_content" = "ะŸะพะฒั–ะดะพะผะธั‚ะธ ะฟั€ะพ ะฒะผั–ัั‚"; "action_reset" = "ะกะบะธะฝัƒั‚ะธ"; +"action_reset_identity" = "ะกะบะธะฝัƒั‚ะธ ั–ะดะตะฝั‚ะธั‡ะฝั–ัั‚ัŒ"; "action_retry" = "ะกะฟั€ะพะฑัƒะฒะฐั‚ะธ ั‰ะต ั€ะฐะท"; "action_retry_decryption" = "ะŸะพะฒั‚ะพั€ะธั‚ะธ ัะฟั€ะพะฑัƒ ั€ะพะทัˆะธั„ั€ัƒะฒะฐะฝะฝั"; "action_save" = "ะ—ะฑะตั€ะตะณั‚ะธ"; @@ -99,10 +104,18 @@ "action_take_photo" = "ะ—ั€ะพะฑะธั‚ะธ ั„ะพั‚ะพ"; "action_tap_for_options" = "ะะฐั‚ะธัะฝั–ั‚ัŒ, ั‰ะพะฑ ะฟะตั€ะตะณะปัะฝัƒั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ะธ"; "action_try_again" = "ะกะฟั€ะพะฑัƒะนั‚ะต ั‰ะต ั€ะฐะท"; +"action_unpin" = "ะ’ั–ะดะบั€ั–ะฟะธั‚ะธ"; +"action_view_in_timeline" = "View in timeline"; "action_view_source" = "ะŸะตั€ะตะณะปัะฝัƒั‚ะธ ะดะถะตั€ะตะปะพ"; "action_yes" = "ะขะฐะบ"; "action.load_more" = "ะ—ะฐะฒะฐะฝั‚ะฐะถะธั‚ะธ ั‰ะต"; -"action.pin" = "Pin"; +"action_deactivate_account" = "Deactivate account"; +"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" = "Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices."; +"banner.set_up_recovery.title" = "Set up recovery"; "common_about" = "ะ’ั–ะดะพะผะพัั‚ั–"; "common_acceptable_use_policy" = "ะŸะพะปั–ั‚ะธะบะฐ ะฟั€ะธะนะฝัั‚ะฝะพะณะพ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั"; "common_advanced_settings" = "ะ”ะพะดะฐั‚ะบะพะฒั– ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั"; @@ -112,7 +125,7 @@ "common_blocked_users" = "ะ—ะฐะฑะปะพะบะพะฒะฐะฝั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–"; "common_bubbles" = "ะ‘ัƒะปัŒะฑะฐัˆะบะธ"; "common_call_invite" = "ะขั€ะธะฒะฐั” ะฒะธะบะปะธะบ (ะฝะต ะฟั–ะดั‚ั€ะธะผัƒั”ั‚ัŒัั)"; -"common_call_started" = "Call started"; +"common_call_started" = "ะ”ะทะฒั–ะฝะพะบ ั€ะพะทะฟะพั‡ะฐั‚ะพ"; "common_chat_backup" = "ะ ะตะทะตั€ะฒะฝะต ะบะพะฟั–ัŽะฒะฐะฝะฝั ั‡ะฐั‚ัƒ"; "common_copyright" = "ะะฒั‚ะพั€ััŒะบะต ะฟั€ะฐะฒะพ"; "common_creating_room" = "ะกั‚ะฒะพั€ะตะฝะฝั ะบั–ะผะฝะฐั‚ะธ..."; @@ -156,7 +169,7 @@ "common_people" = "ะ›ัŽะดะธ"; "common_permalink" = "ะŸะพัั‚ั–ะนะฝะต ะฟะพัะธะปะฐะฝะฝั"; "common_permission" = "ะ”ะพะทะฒั–ะป"; -"common_please_wait" = "Please waitโ€ฆ"; +"common_please_wait" = "ะ‘ัƒะดัŒ ะปะฐัะบะฐ, ะทะฐั‡ะตะบะฐะนั‚ะตโ€ฆ"; "common_poll_total_votes" = "ะ’ััŒะพะณะพ ะณะพะปะพัั–ะฒ: %1$@"; "common_poll_undisclosed_text" = "ะ ะตะทัƒะปัŒั‚ะฐั‚ะธ ะฑัƒะดัƒั‚ัŒ ะฟะพะบะฐะทะฐะฝั– ะฟั–ัะปั ะทะฐะฒะตั€ัˆะตะฝะฝั ะพะฟะธั‚ัƒะฒะฐะฝะฝั"; "common_privacy_policy" = "ะŸะพะปั–ั‚ะธะบะฐ ะบะพะฝั„ั–ะดะตะฝั†ั–ะนะฝะพัั‚ั–"; @@ -212,14 +225,15 @@ "common_voice_message" = "ะ“ะพะปะพัะพะฒะต ะฟะพะฒั–ะดะพะผะปะตะฝะฝั"; "common_waiting" = "ะžั‡ั–ะบัƒะฒะฐะฝะฝั..."; "common_waiting_for_decryption_key" = "ะงะตะบะฐั”ะผะพ ะฝะฐ ั†ะต ะฟะพะฒั–ะดะพะผะปะตะฝะฝั"; -"common.do_not_show_this_again" = "Do not show this again"; -"common.open_source_licenses" = "Open source licenses"; -"common.send_to" = "Send to"; -"common_no_room_name" = "No room name"; +"common.do_not_show_this_again" = "ะะต ะฟะพะบะฐะทัƒะฒะฐั‚ะธ ั†ะต ะทะฝะพะฒัƒ"; +"common.open_source_licenses" = "ะ›ั–ั†ะตะฝะทั–ั— ะฒั–ะดะบั€ะธั‚ะพะณะพ ะบะพะดัƒ"; +"common.pinned" = "Pinned"; +"common.send_to" = "ะะฐะดั–ัะปะฐั‚ะธ ะดะพ"; +"common_no_room_name" = "ะะตะผะฐั” ะฝะฐะทะฒะธ ะบั–ะผะฝะฐั‚ะธ"; "common_poll_end_confirmation" = "ะ’ะธ ะฒะฟะตะฒะฝะตะฝั–, ั‰ะพ ั…ะพั‡ะตั‚ะต ะทะฐะบั–ะฝั‡ะธั‚ะธ ั†ะต ะพะฟะธั‚ัƒะฒะฐะฝะฝั?"; "common_poll_summary" = "ะžะฟะธั‚ัƒะฒะฐะฝะฝั: %1$@"; -"common_something_went_wrong" = "Something went wrong"; -"common_unable_to_decrypt_no_access" = "You don't have access to this message"; +"common_something_went_wrong" = "ะฉะพััŒ ะฟั–ัˆะปะพ ะฝะต ั‚ะฐะบ"; +"common_unable_to_decrypt_no_access" = "ะ’ะธ ะฝะต ะผะฐั”ั‚ะต ะดะพัั‚ัƒะฟัƒ ะดะพ ั†ัŒะพะณะพ ะฟะพะฒั–ะดะพะผะปะตะฝะฝั"; "common_verify_device" = "ะŸะตั€ะตะฒั–ั€ั‚ะต ะฟั€ะธัั‚ั€ั–ะน"; "confirm_recovery_key_banner_message" = "ะ’ะฐัˆะฐ ั€ะตะทะตั€ะฒะฝะฐ ะบะพะฟั–ั ั‡ะฐั‚ัƒ ะฝะฐั€ะฐะทั– ะฝะต ัะธะฝั…ั€ะพะฝั–ะทะพะฒะฐะฝะฐ. ะ’ะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฟั–ะดั‚ะฒะตั€ะดะธั‚ะธ ะบะปัŽั‡ ะฒั–ะดะฝะพะฒะปะตะฝะฝั, ั‰ะพะฑ ะทะฑะตั€ะตะณั‚ะธ ะดะพัั‚ัƒะฟ ะดะพ ั€ะตะทะตั€ะฒะฝะพั— ะบะพะฟั–ั— ั‡ะฐั‚ัƒ."; "confirm_recovery_key_banner_title" = "ะŸั–ะดั‚ะฒะตั€ะดั–ั‚ัŒ ะบะปัŽั‡ ะฒั–ะดะฝะพะฒะปะตะฝะฝั"; @@ -244,20 +258,23 @@ "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_failed_creating_the_permalink" = "ะะต ะฒะดะฐะปะพัั ัั‚ะฒะพั€ะธั‚ะธ ะฟะพัั‚ั–ะนะฝะต ะฟะพัะธะปะฐะฝะฝั"; "error_failed_loading_map" = "%1$@ ะะต ะฒะดะฐะปะพัั ะทะฐะฒะฐะฝั‚ะฐะถะธั‚ะธ ะบะฐั€ั‚ัƒ. ะ‘ัƒะดัŒ ะปะฐัะบะฐ, ัะฟั€ะพะฑัƒะนั‚ะต ั‰ะต ั€ะฐะท ะฟั–ะทะฝั–ัˆะต."; "error_failed_loading_messages" = "ะะต ะฒะดะฐะปะพัั ะทะฐะฒะฐะฝั‚ะฐะถะธั‚ะธ ะฟะพะฒั–ะดะพะผะปะตะฝะฝั"; "error_failed_locating_user" = "%1$@ ะฝะต ะฒะดะฐะปะพัั ะพั‚ั€ะธะผะฐั‚ะธ ะดะพัั‚ัƒะฟ ะดะพ ะฒะฐัˆะพะณะพ ะผั–ัั†ะตะทะฝะฐั…ะพะดะถะตะฝะฝั. ะ‘ัƒะดัŒ ะปะฐัะบะฐ, ัะฟั€ะพะฑัƒะนั‚ะต ั‰ะต ั€ะฐะท ะฟั–ะทะฝั–ัˆะต."; "error_failed_uploading_voice_message" = "ะะต ะฒะดะฐะปะพัั ะทะฐะฒะฐะฝั‚ะฐะถะธั‚ะธ ะณะพะปะพัะพะฒะต ะฟะพะฒั–ะดะพะผะปะตะฝะฝั."; -"error_message_not_found" = "Message not found"; +"error_message_not_found" = "ะŸะพะฒั–ะดะพะผะปะตะฝะฝั ะฝะต ะทะฝะฐะนะดะตะฝะพ"; "error_no_compatible_app_found" = "ะะต ะทะฝะฐะนะดะตะฝะพ ััƒะผั–ัะฝะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ ะดะปั ะฒะธะบะพะฝะฐะฝะฝั ั†ั–ั”ั— ะดั–ั—."; "error_some_messages_have_not_been_sent" = "ะ”ะตัะบั– ะฟะพะฒั–ะดะพะผะปะตะฝะฝั ะฝะต ะฑัƒะปะธ ะฝะฐะดั–ัะปะฐะฝั–"; "error_unknown" = "ะ’ะธะฑะฐั‡ั‚ะต, ัั‚ะฐะปะฐัั ะฟะพะผะธะปะบะฐ"; -"event_shield_reason_authenticity_not_guaranteed" = "The authenticity of this encrypted message can't be guaranteed on this device."; -"event_shield_reason_unknown_device" = "Encrypted by an unknown or deleted device."; -"event_shield_reason_unsigned_device" = "Encrypted by a device not verified by its owner."; -"event_shield_reason_unverified_identity" = "Encrypted by an unverified user."; -"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."; +"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"; "invite_friends_rich_title" = "๐Ÿ”๏ธ ะŸั€ะธั”ะดะฝัƒะนั‚ะตัั ะดะพ ะผะตะฝะต ะฒ %1$@"; "invite_friends_text" = "ะŸั€ะธะฒั–ั‚, ะฟะธัˆั–ั‚ัŒ ะผะตะฝั– ะทะฐ ะฐะดั€ะตัะพัŽ %1$@: %2$@"; @@ -269,17 +286,20 @@ "notification_channel_call" = "ะ’ะธะบะปะธะบ"; "notification_channel_listening_for_events" = "ะŸั€ะพัะปัƒั…ะพะฒัƒะฒะฐะฝะฝั ะฟะพะดั–ะน"; "notification_channel_noisy" = "ะ“ัƒั‡ะฝั– ัะฟะพะฒั–ั‰ะตะฝะฝั"; -"notification_channel_ringing_calls" = "Ringing calls"; +"notification_channel_ringing_calls" = "ะ”ะทะฒั–ะฝะบะธ"; "notification_channel_silent" = "ะขะธั…ั– ัะฟะพะฒั–ั‰ะตะฝะฝั"; -"notification_incoming_call" = "Incoming call"; +"notification_incoming_call" = "ะ’ั…ั–ะดะฝะธะน ะดะทะฒั–ะฝะพะบ"; "notification_inline_reply_failed" = "** ะะต ะฒะดะฐะปะพัั ะฝะฐะดั–ัะปะฐั‚ะธ - ะฑัƒะดัŒ ะปะฐัะบะฐ, ะฒั–ะดะบั€ะธะนั‚ะต ะบั–ะผะฝะฐั‚ัƒ"; "notification_invitation_action_reject" = "ะ’ั–ะดั…ะธะปะธั‚ะธ"; "notification_invite_body" = "ะ—ะฐะฟั€ะพัะธะฒ (-ะปะฐ) ะ’ะฐั ะดะพ ั‡ะฐั‚ัƒ"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "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_sender_me" = "ะฏ"; +"notification_sender_mention_reply" = "%1$@ mentioned or replied"; "notification_test_push_notification_content" = "ะ’ะธ ะฟะตั€ะตะณะปัะดะฐั”ั‚ะต ัะฟะพะฒั–ั‰ะตะฝะฝั! ะะฐั‚ะธัะฝั–ั‚ัŒ ั‚ัƒั‚!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -312,10 +332,27 @@ "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_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_pinned_timeline_screen_title_empty" = "Pinned messages"; +"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.room.pinned_banner_indicator" = "%1$@ of %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ Pinned messages"; -"screen.room.pinned_banner_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_view_all_button_title" = "ะŸะตั€ะตะณะปัะฝัƒั‚ะธ ะฒัั–"; +"screen_room_details_pinned_events_row_title" = "Pinned messages"; +"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_account_provider_change" = "ะ—ะผั–ะฝะธั‚ะธ ะฟั€ะพะฒะฐะนะดะตั€ะฐ ะพะฑะปั–ะบะพะฒะพะณะพ ะทะฐะฟะธััƒ"; "screen_account_provider_form_hint" = "ะะดั€ะตัะฐ ะดะพะผะฐัˆะฝัŒะพะณะพ ัะตั€ะฒะตั€ะฐ"; "screen_account_provider_form_notice" = "ะฃะฒะตะดั–ั‚ัŒ ะฟะพัˆัƒะบะพะฒะธะน ั‚ะตั€ะผั–ะฝ ะฐะฑะพ ะฐะดั€ะตััƒ ะดะพะผะตะฝัƒ."; @@ -398,13 +435,14 @@ "screen_chat_backup_recovery_action_confirm_description" = "ะ’ะฐัˆะฐ ั€ะตะทะตั€ะฒะฝะฐ ะบะพะฟั–ั ั‡ะฐั‚ัƒ ะฝะฐั€ะฐะทั– ะฝะต ัะธะฝั…ั€ะพะฝั–ะทะพะฒะฐะฝะฐ."; "screen_chat_backup_recovery_action_setup" = "ะะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ะฒั–ะดะฝะพะฒะปะตะฝะฝั"; "screen_chat_backup_recovery_action_setup_description" = "ะžั‚ั€ะธะผะฐะนั‚ะต ะดะพัั‚ัƒะฟ ะดะพ ัะฒะพั—ั… ะทะฐัˆะธั„ั€ะพะฒะฐะฝะธั… ะฟะพะฒั–ะดะพะผะปะตะฝัŒ, ัะบั‰ะพ ะฒะธ ะฒั‚ั€ะฐั‚ะธั‚ะต ะฒัั– ัะฒะพั— ะฟั€ะธัั‚ั€ะพั— ะฐะฑะพ ะฒะธะนัˆะปะธ ะท %1$@ ัะธัั‚ะตะผะธ."; -"screen_create_new_recovery_key_list_item_1" = "Open %1$@ in a desktop device"; -"screen_create_new_recovery_key_list_item_2" = "Sign into your account again"; -"screen_create_new_recovery_key_list_item_3" = "When asked to verify your device, select %1$@"; -"screen_create_new_recovery_key_list_item_3_reset_all" = "โ€œReset allโ€"; -"screen_create_new_recovery_key_list_item_4" = "Follow the instructions to create a new recovery key"; -"screen_create_new_recovery_key_list_item_5" = "Save your new recovery key in a password manager or encrypted note"; -"screen_create_new_recovery_key_title" = "Reset the encryption for your account using another device"; +"screen_create_account_title" = "Create account"; +"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$@"; +"screen_create_new_recovery_key_list_item_3_reset_all" = "โ€œะกะบะธะฝัƒั‚ะธ ะฒัะตโ€"; +"screen_create_new_recovery_key_list_item_4" = "ะ”ะพั‚ั€ะธะผัƒะนั‚ะตััŒ ั–ะฝัั‚ั€ัƒะบั†ั–ะน, ั‰ะพะฑ ัั‚ะฒะพั€ะธั‚ะธ ะฝะพะฒะธะน ะบะปัŽั‡ ะฒั–ะดะฝะพะฒะปะตะฝะฝั"; +"screen_create_new_recovery_key_list_item_5" = "ะ—ะฑะตั€ะตะถั–ั‚ัŒ ะฝะพะฒะธะน ะบะปัŽั‡ ะฒั–ะดะฝะพะฒะปะตะฝะฝั ัƒ ะผะตะฝะตะดะถะตั€ั– ะฟะฐั€ะพะปั–ะฒ ะฐะฑะพ ะทะฐัˆะธั„ั€ะพะฒะฐะฝั–ะน ะฝะพั‚ะฐั‚ั†ั–"; +"screen_create_new_recovery_key_title" = "ะกะบะธะฝัƒั‚ะธ ัˆะธั„ั€ัƒะฒะฐะฝะฝั ะพะฑะปั–ะบะพะฒะพะณะพ ะทะฐะฟะธััƒ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ั–ะฝัˆะพะณะพ ะฟั€ะธัั‚ั€ะพัŽ"; "screen_create_poll_add_option_btn" = "ะ”ะพะดะฐั‚ะธ ะฒะฐั€ั–ะฐะฝั‚"; "screen_create_poll_anonymous_desc" = "ะŸะพะบะฐะทัƒะฒะฐั‚ะธ ั€ะตะทัƒะปัŒั‚ะฐั‚ะธ ั‚ั–ะปัŒะบะธ ะฟั–ัะปั ะทะฐะบั–ะฝั‡ะตะฝะฝั ะพะฟะธั‚ัƒะฒะฐะฝะฝั"; "screen_create_poll_anonymous_headline" = "ะŸั€ะธั…ะพะฒะฐั‚ะธ ะณะพะปะพัะธ"; @@ -421,6 +459,17 @@ "screen_create_room_public_option_description" = "ะŸะพะฒั–ะดะพะผะปะตะฝะฝั ะฝะต ัˆะธั„ั€ัƒัŽั‚ัŒัั, ั– ะฑัƒะดัŒ-ั…ั‚ะพ ะผะพะถะต ั—ั… ะฟั€ะพั‡ะธั‚ะฐั‚ะธ. ะจะธั„ั€ัƒะฒะฐะฝะฝั ะผะพะถะฝะฐ ะฒะฒั–ะผะบะฝัƒั‚ะธ ะฟั–ะทะฝั–ัˆะต."; "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_edit_poll_delete_confirmation" = "ะ’ะธ ะฒะฟะตะฒะฝะตะฝั–, ั‰ะพ ั…ะพั‡ะตั‚ะต ะฒะธะดะฐะปะธั‚ะธ ั†ะต ะพะฟะธั‚ัƒะฒะฐะฝะฝั?"; "screen_edit_profile_display_name" = "ะ’ั–ะดะพะฑั€ะฐะถัƒะฒะฐะฝะต ั–ะผ'ั"; "screen_edit_profile_display_name_placeholder" = "ะ’ะฐัˆะต ะฒั–ะดะพะฑั€ะฐะถัƒะฒะฐะฝะต ั–ะผ'ั"; @@ -428,27 +477,35 @@ "screen_edit_profile_error_title" = "ะะตะผะพะถะปะธะฒะพ ะพะฝะพะฒะธั‚ะธ ะฟั€ะพั„ั–ะปัŒ"; "screen_edit_profile_title" = "ะ ะตะดะฐะณัƒะฒะฐั‚ะธ ะฟั€ะพั„ั–ะปัŒ"; "screen_edit_profile_updating_details" = "ะžะฝะพะฒะปะตะฝะฝั ะฟั€ะพั„ั–ะปัŽ..."; -"screen_identity_confirmation_create_new_recovery_key" = "Create a new recovery key"; +"screen_encryption_reset_action_continue_reset" = "Continue reset"; +"screen_encryption_reset_bullet_1" = "ะ”ะฐะฝั– ะฒะฐัˆะพะณะพ ะพะฑะปั–ะบะพะฒะพะณะพ ะทะฐะฟะธััƒ, ะบะพะฝั‚ะฐะบั‚ะธ, ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ะน ั‡ะฐั‚ะธ ะฑัƒะดัƒั‚ัŒ ะทะฑะตั€ะตะถะตะฝั–"; +"screen_encryption_reset_bullet_2" = "ะ’ะธ ะฒั‚ั€ะฐั‚ะธั‚ะต ัะฒะพัŽ ะฝะฐัะฒะฝัƒ ั–ัั‚ะพั€ั–ัŽ ะฟะพะฒั–ะดะพะผะปะตะฝัŒ"; +"screen_encryption_reset_bullet_3" = "ะ’ะฐะผ ะดะพะฒะตะดะตั‚ัŒัั ะฟั–ะดั‚ะฒะตั€ะดะธั‚ะธ ะฒัั– ะฝะฐัะฒะฝั– ะฟั€ะธัั‚ั€ะพั— ั‚ะฐ ะบะพะฝั‚ะฐะบั‚ะธ ะทะฝะพะฒัƒ"; +"screen_encryption_reset_footer" = "ะกะบะธะดะฐะนั‚ะต ั–ะดะตะฝั‚ะธั‡ะฝั–ัั‚ัŒ ั‚ั–ะปัŒะบะธ ัะบั‰ะพ ะฒะธ ะฝะต ะผะฐั”ั‚ะต ะดะพัั‚ัƒะฟัƒ ะดะพ ั–ะฝัˆะธั… ะฟั€ะธัั‚ั€ะพั—ะฒ ะฒ ะพะฑะปั–ะบะพะฒะพะผัƒ ะทะฐะฟะธัั– ั‚ะฐ ะฒั‚ั€ะฐั‚ะธะปะธ ัะฒั–ะน ะบะปัŽั‡ ะฒั–ะดะฝะพะฒะปะตะฝะฝั."; +"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_confirmed_subtitle" = "ะขะตะฟะตั€ ะฒะธ ะผะพะถะตั‚ะต ะฑะตะทะฟะตั‡ะฝะพ ั‡ะธั‚ะฐั‚ะธ ะฐะฑะพ ะฝะฐะดัะธะปะฐั‚ะธ ะฟะพะฒั–ะดะพะผะปะตะฝะฝั, ั– ะบะพะถะตะฝ, ะท ะบะธะผ ะฒะธ ัะฟั–ะปะบัƒั”ั‚ะตััŒ, ั‚ะฐะบะพะถ ะผะพะถะต ะดะพะฒั–ั€ัั‚ะธ ั†ัŒะพะผัƒ ะฟั€ะธัั‚ั€ะพัŽ."; "screen_identity_confirmed_title" = "ะŸั€ะธัั‚ั€ั–ะน ะฟะตั€ะตะฒั–ั€ะตะฝะพ"; -"screen_identity_use_another_device" = "Use another device"; -"screen_identity_waiting_on_other_device" = "Waiting on other deviceโ€ฆ"; +"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_empty_list" = "ะะตะผะฐั” ะทะฐะฟั€ะพัˆะตะฝัŒ"; "screen_invites_invited_you" = "%1$@ (%2$@) ะทะฐะฟั€ะพัะธะฒ (-ะปะฐ) ะ’ะฐั"; -"screen_join_room_join_action" = "Join room"; -"screen_join_room_knock_action" = "Knock to join"; -"screen_join_room_space_not_supported_description" = "%1$@ does not support spaces yet. You can access spaces on web."; -"screen_join_room_space_not_supported_title" = "Spaces are not supported yet"; -"screen_join_room_subtitle_knock" = "Click the button below and a room administrator will be notified. Youโ€™ll be able to join the conversation once approved."; -"screen_join_room_subtitle_no_preview" = "You must be a member of this room to view the message history."; -"screen_join_room_title_knock" = "Want to join this room?"; -"screen_join_room_title_no_preview" = "Preview is not available"; +"screen_join_room_join_action" = "ะŸั€ะธั”ะดะฝะฐั‚ะธัั ะดะพ ะบั–ะผะฝะฐั‚ะธ"; +"screen_join_room_knock_action" = "ะŸะพัั‚ัƒะบะฐั‚ะธ, ั‰ะพะฑ ะฟั€ะธั”ะดะฝะฐั‚ะธัั"; +"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" = "ะ’ะธ ะผัƒัะธั‚ะต ะฑัƒั‚ะธ ัƒั‡ะฐัะฝะธะบะพะผ ั†ั–ั”ั— ะบั–ะผะฝะฐั‚ะธ, ั‰ะพะฑ ะฟะตั€ะตะณะปัะดะฐั‚ะธ ั–ัั‚ะพั€ั–ัŽ ะฟะพะฒั–ะดะพะผะปะตะฝัŒ."; +"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" = "ะ’ะธ ะฒั‚ั€ะฐั‚ะธั‚ะต ะทะฐัˆะธั„ั€ะพะฒะฐะฝั– ะฟะพะฒั–ะดะพะผะปะตะฝะฝั, ัะบั‰ะพ ะฒะธะนะดะตั‚ะต ะท ัƒัั–ั… ะฟั€ะธัั‚ั€ะพั—ะฒ."; "screen_key_backup_disable_confirmation_title" = "ะ’ะธ ะฒะฟะตะฒะฝะตะฝั–, ั‰ะพ ั…ะพั‡ะตั‚ะต ะฒะธะผะบะฝัƒั‚ะธ ั€ะตะทะตั€ะฒะฝะต ะบะพะฟั–ัŽะฒะฐะฝะฝั?"; @@ -507,58 +564,57 @@ "screen_polls_history_filter_ongoing" = "ะŸะพั‚ะพั‡ะฝั–"; "screen_polls_history_filter_past" = "ะœะธะฝัƒะปั–"; "screen_polls_history_title" = "ะžะฟะธั‚ัƒะฒะฐะฝะฝั"; -"screen_qr_code_login_connecting_subtitle" = "Establishing a secure connection"; -"screen_qr_code_login_connection_note_secure_state_description" = "A secure connection could not be made to the new device. Your existing devices are still safe and you don't need to worry about them."; -"screen_qr_code_login_connection_note_secure_state_list_header" = "What now?"; -"screen_qr_code_login_connection_note_secure_state_list_item_1" = "Try signing in again with a QR code in case this was a network problem"; -"screen_qr_code_login_connection_note_secure_state_list_item_2" = "If you encounter the same problem, try a different wifi network or use your mobile data instead of wifi"; -"screen_qr_code_login_connection_note_secure_state_list_item_3" = "If that doesnโ€™t work, sign in manually"; -"screen_qr_code_login_connection_note_secure_state_title" = "Connection not secure"; -"screen_qr_code_login_device_code_subtitle" = "Youโ€™ll be asked to enter the two digits shown on this device."; -"screen_qr_code_login_device_code_title" = "Enter the number below on your other device"; -"screen_qr_code_login_device_not_signed_in_scan_state_description" = "Sign in to your other device and then try again, or use another device thatโ€™s already signed in."; -"screen_qr_code_login_device_not_signed_in_scan_state_subtitle" = "Other device not signed in"; -"screen_qr_code_login_error_cancelled_subtitle" = "The sign in was cancelled on the other device."; -"screen_qr_code_login_error_cancelled_title" = "Sign in request cancelled"; -"screen_qr_code_login_error_declined_subtitle" = "The sign in was declined on the other device."; -"screen_qr_code_login_error_declined_title" = "Sign in declined"; -"screen_qr_code_login_error_expired_subtitle" = "Sign in expired. Please try again."; -"screen_qr_code_login_error_expired_title" = "The sign in was not completed in time"; -"screen_qr_code_login_error_linking_not_suported_subtitle" = "Your other device does not support signing in to %@ with a QR code.\n\nTry signing in manually, or scan the QR code with another device."; -"screen_qr_code_login_error_linking_not_suported_title" = "QR code not supported"; -"screen_qr_code_login_error_sliding_sync_not_supported_subtitle" = "Your account provider does not support %1$@."; -"screen_qr_code_login_error_sliding_sync_not_supported_title" = "%1$@ not supported"; -"screen_qr_code_login_initial_state_button_title" = "Ready to scan"; -"screen_qr_code_login_initial_state_item_1" = "Open %1$@ on a desktop device"; -"screen_qr_code_login_initial_state_item_2" = "Click on your avatar"; -"screen_qr_code_login_initial_state_item_3" = "Select %1$@"; -"screen_qr_code_login_initial_state_item_3_action" = "โ€œLink new deviceโ€"; -"screen_qr_code_login_initial_state_item_4" = "Scan the QR code with this device"; -"screen_qr_code_login_initial_state_title" = "Open %1$@ on another device to get the QR code"; -"screen_qr_code_login_invalid_scan_state_description" = "Use the QR code shown on the other device."; -"screen_qr_code_login_invalid_scan_state_subtitle" = "Wrong QR code"; -"screen_qr_code_login_no_camera_permission_button" = "Go to camera settings"; -"screen_qr_code_login_no_camera_permission_state_description" = "You need to give permission for %1$@ to use your deviceโ€™s camera in order to continue."; -"screen_qr_code_login_no_camera_permission_state_title" = "Allow camera access to scan the QR code"; -"screen_qr_code_login_scanning_state_title" = "Scan the QR code"; -"screen_qr_code_login_start_over_button" = "Start over"; -"screen_qr_code_login_unknown_error_description" = "An unexpected error occurred. Please try again."; -"screen_qr_code_login_verify_code_loading" = "Waiting for your other device"; -"screen_qr_code_login_verify_code_subtitle" = "Your account provider may ask for the following code to verify the sign in."; -"screen_qr_code_login_verify_code_title" = "Your verification code"; +"screen_qr_code_login_connecting_subtitle" = "ะ’ัั‚ะฐะฝะพะฒะปะตะฝะฝั ะฑะตะทะฟะตั‡ะฝะพะณะพ ะท'ั”ะดะฝะฐะฝะฝั"; +"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_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_error_cancelled_subtitle" = "ะ’ั…ั–ะด ะฑัƒะปะพ ัะบะฐัะพะฒะฐะฝะพ ะฝะฐ ั–ะฝัˆะพะผัƒ ะฟั€ะธัั‚ั€ะพั—."; +"screen_qr_code_login_error_cancelled_title" = "ะ—ะฐะฟะธั‚ ะฝะฐ ะฒั…ั–ะด ัะบะฐัะพะฒะฐะฝะพ"; +"screen_qr_code_login_error_declined_subtitle" = "ะ’ั…ั–ะด ะฑัƒะฒ ะฒั–ะดั…ะธะปะตะฝะธะน ะฝะฐ ั–ะฝัˆะพะผัƒ ะฟั€ะธัั‚ั€ะพั—."; +"screen_qr_code_login_error_declined_title" = "ะ’ั…ั–ะด ะฒั–ะดั…ะธะปะตะฝะพ"; +"screen_qr_code_login_error_expired_subtitle" = "ะขะตั€ะผั–ะฝ ะฒั…ะพะดัƒ ัะฟะปะธะฒ. ะ‘ัƒะดัŒ ะปะฐัะบะฐ, ัะฟั€ะพะฑัƒะนั‚ะต ั‰ะต ั€ะฐะท."; +"screen_qr_code_login_error_expired_title" = "ะ’ั…ั–ะด ะฝะต ะฑัƒะปะพ ะทะฐะฒะตั€ัˆะตะฝะพ ะฒั‡ะฐัะฝะพ"; +"screen_qr_code_login_error_linking_not_suported_subtitle" = "ะ’ะฐัˆ ั–ะฝัˆะธะน ะฟั€ะธัั‚ั€ั–ะน ะฝะต ะฟั–ะดั‚ั€ะธะผัƒั” ะฒั…ั–ะด ัƒ %@ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ QR-ะบะพะดัƒ.\n\nะกะฟั€ะพะฑัƒะนั‚ะต ะฒะฒั–ะนั‚ะธ ะฒั€ัƒั‡ะฝัƒ ะฐะฑะพ ะฒั–ะดัะบะฐะฝัƒะนั‚ะต QR-ะบะพะด ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ั–ะฝัˆะพะณะพ ะฟั€ะธัั‚ั€ะพัŽ."; +"screen_qr_code_login_error_linking_not_suported_title" = "QR-ะบะพะด ะฝะต ะฟั–ะดั‚ั€ะธะผัƒั”ั‚ัŒัั"; +"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$@ ะฝะฐ ะบะพะผะฟ'ัŽั‚ะตั€ั–"; +"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_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_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_generate_key" = "ะ—ะณะตะฝะตั€ัƒะฒะฐั‚ะธ ะฝะพะฒะธะน ะบะปัŽั‡ ะฒั–ะดะฝะพะฒะปะตะฝะฝั"; "screen_recovery_key_change_generate_key_description" = "ะŸะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะฒะธ ะผะพะถะตั‚ะต ะทะฑะตั€ั–ะณะฐั‚ะธ ะบะปัŽั‡ ะฒั–ะดะฝะพะฒะปะตะฝะฝั ะฒ ะฑะตะทะฟะตั‡ะฝะพะผัƒ ะผั–ัั†ั–"; "screen_recovery_key_change_success" = "ะšะปัŽั‡ ะฒั–ะดะฝะพะฒะปะตะฝะฝั ะทะผั–ะฝะตะฝะพ"; "screen_recovery_key_change_title" = "ะ—ะผั–ะฝะธั‚ะธ ะบะปัŽั‡ ะฒั–ะดะฝะพะฒะปะตะฝะฝั?"; -"screen_recovery_key_confirm_create_new_recovery_key" = "Create new recovery key"; -"screen_recovery_key_confirm_description" = "ะ’ะฒะตะดั–ั‚ัŒ ะบะปัŽั‡ ะฒั–ะดะฝะพะฒะปะตะฝะฝั, ั‰ะพะฑ ะฟั–ะดั‚ะฒะตั€ะดะธั‚ะธ ะดะพัั‚ัƒะฟ ะดะพ ั€ะตะทะตั€ะฒะฝะพั— ะบะพะฟั–ั— ั‡ะฐั‚ัƒ."; +"screen_recovery_key_confirm_create_new_recovery_key" = "ะกั‚ะฒะพั€ะธั‚ะธ ะฝะพะฒะธะน ะบะปัŽั‡ ะฒั–ะดะฝะพะฒะปะตะฝะฝั"; +"screen_recovery_key_confirm_description" = "ะ’ะฟะตะฒะฝั–ั‚ัŒัั, ั‰ะพ ะฝั–ั…ั‚ะพ ะฝะต ะดะธะฒะธั‚ัŒัั!"; "screen_recovery_key_confirm_error_content" = "ะ‘ัƒะดัŒ ะปะฐัะบะฐ, ัะฟั€ะพะฑัƒะนั‚ะต ั‰ะต ั€ะฐะท, ั‰ะพะฑ ะฟั–ะดั‚ะฒะตั€ะดะธั‚ะธ ะดะพัั‚ัƒะฟ ะดะพ ั€ะตะทะตั€ะฒะฝะพั— ะบะพะฟั–ั— ั‡ะฐั‚ัƒ."; "screen_recovery_key_confirm_error_title" = "ะะตะฟั€ะฐะฒะธะปัŒะฝะธะน ะบะปัŽั‡ ะฒั–ะดะฝะพะฒะปะตะฝะฝั"; -"screen_recovery_key_confirm_key_description" = "ะ’ะฒะตะดั–ั‚ัŒ ะบะพะด ั–ะท 48 ัะธะผะฒะพะปั–ะฒ."; -"screen_recovery_key_confirm_key_label" = "Recovery key or passcode"; +"screen_recovery_key_confirm_key_description" = "ะฏะบั‰ะพ ัƒ ะฒะฐั ั” ะบะปัŽั‡ ะฑะตะทะฟะตะบะธ ะฐะฑะพ ั„ั€ะฐะทะฐ ะฑะตะทะฟะตะบะธ, ั†ะต ั‚ะตะถ ัะฟั€ะฐั†ัŽั”."; "screen_recovery_key_confirm_key_placeholder" = "ะ’ะฒะตัั‚ะธ..."; -"screen_recovery_key_confirm_lost_recovery_key" = "Lost your recovery key?"; +"screen_recovery_key_confirm_lost_recovery_key" = "ะ—ะฐะณัƒะฑะธะปะธ ะบะปัŽั‡ ะฒั–ะดะฝะพะฒะปะตะฝะฝั?"; "screen_recovery_key_confirm_success" = "ะšะปัŽั‡ ะฒั–ะดะฝะพะฒะปะตะฝะฝั ะฟั–ะดั‚ะฒะตั€ะดะถะตะฝะพ"; "screen_recovery_key_confirm_title" = "ะŸั–ะดั‚ะฒะตั€ะดั–ั‚ัŒ ะบะปัŽั‡ ะฒั–ะดะฝะพะฒะปะตะฝะฝั"; "screen_recovery_key_copied_to_clipboard" = "ะกะบะพะฟั–ะนะพะฒะฐะฝะพ ะบะปัŽั‡ ะฒั–ะดะฝะพะฒะปะตะฝะฝั"; @@ -577,7 +633,15 @@ "screen_report_content_block_user_hint" = "ะŸะตั€ะตะฒั–ั€ั‚ะต, ั‡ะธ ั…ะพั‡ะตั‚ะต ะ’ะธ ะฟั€ะธั…ะพะฒะฐั‚ะธ ะฒัั– ะฟะพั‚ะพั‡ะฝั– ั‚ะฐ ะผะฐะนะฑัƒั‚ะฝั– ะฟะพะฒั–ะดะพะผะปะตะฝะฝั ะฒั–ะด ั†ัŒะพะณะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ"; "screen_report_content_explanation" = "ะฆะต ะฟะพะฒั–ะดะพะผะปะตะฝะฝั ะฑัƒะดะต ะฝะฐะดั–ัะปะฐะฝะพ ะฐะดะผั–ะฝั–ัั‚ั€ะฐั‚ะพั€ัƒ ะฒะฐัˆะพะณะพ ะดะพะผะฐัˆะฝัŒะพะณะพ ัะตั€ะฒะตั€ะฐ. ะ’ั–ะฝ (ะฒะพะฝะฐ) ะฝะต ะทะผะพะถะต ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ะถะพะดะฝั– ะทะฐัˆะธั„ั€ะพะฒะฐะฝั– ะฟะพะฒั–ะดะพะผะปะตะฝะฝั."; "screen_report_content_hint" = "ะŸั€ะธั‡ะธะฝะฐ ัะบะฐั€ะณะธ ะฝะฐ ั†ะตะน ะฒะผั–ัั‚"; -"screen_room_alias_resolver_resolve_alias_failure" = "Failed to resolve room alias."; +"screen_reset_encryption_confirmation_alert_action" = "ะขะฐะบ, ัะบะธะฝัƒั‚ะธ ะทะฐั€ะฐะท"; +"screen_reset_encryption_confirmation_alert_subtitle" = "ะฆะตะน ะฟั€ะพั†ะตั ะฝะตะทะฒะพั€ะพั‚ะฝะธะน."; +"screen_reset_encryption_confirmation_alert_title" = "ะ’ะธ ะฒะฟะตะฒะฝะตะฝั–, ั‰ะพ ั…ะพั‡ะตั‚ะต ัะบะธะฝัƒั‚ะธ ัˆะธั„ั€ัƒะฒะฐะฝะฝั?"; +"screen_reset_encryption_password_placeholder" = "ะ’ะฒะตัั‚ะธโ€ฆ"; +"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_room_alias_resolver_resolve_alias_failure" = "ะะต ะฒะดะฐะปะพัั ั€ะพะทะฒ'ัะทะฐั‚ะธ ะฟัะตะฒะดะพะฝั–ะผ ะบั–ะผะฝะฐั‚ะธ."; "screen_room_attachment_source_camera" = "ะšะฐะผะตั€ะฐ"; "screen_room_attachment_source_camera_video" = "ะ—ะฐะฟะธัะฐั‚ะธ ะฒั–ะดะตะพ"; "screen_room_attachment_source_files" = "ะ’ะบะปะฐะดะตะฝะฝั"; @@ -601,17 +665,17 @@ "screen_room_change_role_confirm_demote_self_action" = "ะŸะพะฝะธะทะธั‚ะธ"; "screen_room_change_role_confirm_demote_self_description" = "ะ’ะธ ะฝะต ะทะผะพะถะตั‚ะต ัะบะฐััƒะฒะฐั‚ะธ ั†ัŽ ะทะผั–ะฝัƒ, ะพัะบั–ะปัŒะบะธ ะฒะธ ะทะฝะธะถัƒั”ั‚ะต ัะตะฑะต, ัะบั‰ะพ ะฒะธ ะพัั‚ะฐะฝะฝั–ะน ะฟั€ะธะฒั–ะปะตะนะพะฒะฐะฝะธะน ะบะพั€ะธัั‚ัƒะฒะฐั‡ ัƒ ะบั–ะผะฝะฐั‚ั–, ะฒั–ะดะฝะพะฒะธั‚ะธ ะฟั€ะธะฒั–ะปะตั— ะฑัƒะดะต ะฝะตะผะพะถะปะธะฒะพ."; "screen_room_change_role_confirm_demote_self_title" = "ะŸะพะฝะธะทะธั‚ะธ ัะตะฑะต?"; -"screen_room_change_role_invited_member_name" = "%1$@ (Pending)"; -"screen_room_change_role_moderators_admin_section_footer" = "Admins automatically have moderator privileges"; +"screen_room_change_role_invited_member_name" = "%1$@ (ะžั‡ั–ะบัƒั”ั‚ัŒัั)"; +"screen_room_change_role_moderators_admin_section_footer" = "ะะดะผั–ะฝั–ัั‚ั€ะฐั‚ะพั€ะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะผะฐัŽั‚ัŒ ะฟั€ะฐะฒะฐ ะผะพะดะตั€ะฐั‚ะพั€ะฐ"; "screen_room_change_role_moderators_title" = "ะšะตั€ัƒะฒะฐั‚ะธ ะผะพะดะตั€ะฐั‚ะพั€ะฐะผะธ"; "screen_room_change_role_unsaved_changes_description" = "ะฃ ะฒะฐั ั” ะฝะต ะทะฑะตั€ะตะถะตะฝั– ะทะผั–ะฝะธ."; "screen_room_change_role_unsaved_changes_title" = "ะ—ะฑะตั€ะตะณั‚ะธ ะทะผั–ะฝะธ?"; "screen_room_details_add_topic_title" = "ะ”ะพะดะฐั‚ะธ ั‚ะตะผัƒ"; "screen_room_details_already_a_member" = "ะฃะถะต ัƒั‡ะฐัะฝะธะบ"; "screen_room_details_already_invited" = "ะฃะถะต ะทะฐะฟั€ะพัˆะตะฝั–"; -"screen_room_details_badge_encrypted" = "Encrypted"; -"screen_room_details_badge_not_encrypted" = "Not encrypted"; -"screen_room_details_badge_public" = "Public room"; +"screen_room_details_badge_encrypted" = "ะ—ะฐัˆะธั„ั€ะพะฒะฐะฝะพ"; +"screen_room_details_badge_not_encrypted" = "ะะต ะทะฐัˆะธั„ั€ะพะฒะฐะฝะพ"; +"screen_room_details_badge_public" = "ะŸัƒะฑะปั–ั‡ะฝะฐ ะบั–ะผะฝะฐั‚ะฐ"; "screen_room_details_edit_room_title" = "ะ ะตะดะฐะณัƒะฒะฐั‚ะธ ะบั–ะผะฝะฐั‚ัƒ"; "screen_room_details_edition_error" = "ะกั‚ะฐะปะฐัั ะฝะตะฒั–ะดะพะผะฐ ะฟะพะผะธะปะบะฐ, ะน ั–ะฝั„ะพั€ะผะฐั†ั–ัŽ ะฝะต ะฒะดะฐะปะพัั ะทะผั–ะฝะธั‚ะธ."; "screen_room_details_edition_error_title" = "ะะต ะฒะดะฐะปะพัั ะพะฝะพะฒะธั‚ะธ ะบั–ะผะฝะฐั‚ัƒ"; @@ -624,7 +688,7 @@ "screen_room_details_notification_mode_default" = "ะ—ะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ"; "screen_room_details_notification_title" = "ะกะฟะพะฒั–ั‰ะตะฝะฝั"; "screen_room_details_share_room_title" = "ะŸะพะดั–ะปะธั‚ะธัั ะบั–ะผะฝะฐั‚ะพัŽ"; -"screen_room_details_title" = "Room info"; +"screen_room_details_title" = "ะ†ะฝั„ะพั€ะผะฐั†ั–ั ะฟั€ะพ ะบั–ะผะฝะฐั‚ัƒ"; "screen_room_details_updating_room" = "ะžะฝะพะฒะปะตะฝะฝั ะบั–ะผะฝะฐั‚ะธ..."; "screen_room_directory_search_loading_error" = "ะะต ะฒะดะฐะปะพัั ะทะฐะฒะฐะฝั‚ะฐะถะธั‚ะธ"; "screen_room_directory_search_title" = "ะšะฐั‚ะฐะปะพะณ ะบั–ะผะฝะฐั‚"; @@ -636,7 +700,7 @@ "screen_room_member_details_block_alert_action" = "ะ—ะฐะฑะปะพะบัƒะฒะฐั‚ะธ"; "screen_room_member_details_block_alert_description" = "ะ—ะฐะฑะปะพะบะพะฒะฐะฝั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ั– ะฝะต ะทะผะพะถัƒั‚ัŒ ะฝะฐะดัะธะปะฐั‚ะธ ะ’ะฐะผ ะฟะพะฒั–ะดะพะผะปะตะฝะฝั, ั– ะฒัั– ั—ั…ะฝั– ะฟะพะฒั–ะดะพะผะปะตะฝะฝั ะฑัƒะดัƒั‚ัŒ ะฟั€ะธั…ะพะฒะฐะฝั–. ะ’ะธ ะผะพะถะตั‚ะต ั€ะพะทะฑะปะพะบัƒะฒะฐั‚ะธ ั—ั… ัƒ ะฑัƒะดัŒ-ัะบะธะน ั‡ะฐั."; "screen_room_member_details_block_user" = "ะ—ะฐะฑะปะพะบัƒะฒะฐั‚ะธ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ"; -"screen_room_member_details_title" = "Profile"; +"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" = "ะ ะพะทะฑะปะพะบัƒะฒะฐั‚ะธ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ"; @@ -700,7 +764,7 @@ "screen_room_timeline_reactions_show_less" = "ะŸะพะบะฐะทัƒะฒะฐั‚ะธ ะผะตะฝัˆะต"; "screen_room_timeline_reactions_show_more" = "ะŸะพะบะฐะทะฐั‚ะธ ะฑั–ะปัŒัˆะต"; "screen_room_timeline_read_marker_title" = "ะะพะฒะต"; -"screen_room_title" = "Chat"; +"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" = " ะฟะธัˆะตโ€ฆ"; @@ -712,8 +776,8 @@ "screen_roomlist_filter_favourites" = "ะฃะปัŽะฑะปะตะฝั–"; "screen_roomlist_filter_favourites_empty_state_subtitle" = "ะ’ะธ ะผะพะถะตั‚ะต ะดะพะดะฐั‚ะธ ั‡ะฐั‚ ะดะพ ัƒะปัŽะฑะปะตะฝะธั… ัƒ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝัั… ั‡ะฐั‚ัƒ.\nะะฐั€ะฐะทั– ะฒะธ ะผะพะถะตั‚ะต ะทะฝัั‚ะธ ั„ั–ะปัŒั‚ั€ะธ, ั‰ะพะฑ ะฟะพะฑะฐั‡ะธั‚ะธ ั–ะฝัˆั– ะฒะฐัˆั– ั‡ะฐั‚ะธ"; "screen_roomlist_filter_favourites_empty_state_title" = "ะ’ะธ ั‰ะต ะฝะต ะผะฐั”ั‚ะต ัƒะปัŽะฑะปะตะฝะธั… ั‡ะฐั‚ั–ะฒ"; -"screen_roomlist_filter_invites" = "Invites"; -"screen_roomlist_filter_invites_empty_state_title" = "You don't have any pending invites."; +"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" = "ะ’ะธ ะฝะต ะผะฐั”ั‚ะต ั‡ะฐั‚ั–ะฒ ะดะปั ั†ั–ั”ั— ะบะฐั‚ะตะณะพั€ั–ั—"; @@ -723,9 +787,9 @@ "screen_roomlist_filter_unreads" = "ะะตะฟั€ะพั‡ะธั‚ะฐะฝั–"; "screen_roomlist_filter_unreads_empty_state_title" = "ะ’ั–ั‚ะฐั”ะผะพ!\nะฃ ะฒะฐั ะฝะตะผะฐั” ะฝะตะฟั€ะพั‡ะธั‚ะฐะฝะธั… ะฟะพะฒั–ะดะพะผะปะตะฝัŒ!"; "screen_roomlist_main_space_title" = "ะฃัั– ั‡ะฐั‚ะธ"; -"screen_roomlist_mark_as_read" = "ะŸะพะทะฝะฐั‡ะธั‚ะธ ัะบ ะฟั€ะพั‡ะธั‚ะฐะฝะต"; -"screen_roomlist_mark_as_unread" = "ะŸะพะทะฝะฐั‡ะธั‚ะธ ัะบ ะฝะตะฟั€ะพั‡ะธั‚ะฐะฝะต"; -"screen_roomlist_room_directory_button_title" = "Browse all rooms"; +"screen_roomlist_mark_as_read" = "ะŸะพะทะฝะฐั‡ะธั‚ะธ ะฟั€ะพั‡ะธั‚ะฐะฝะธะผ"; +"screen_roomlist_mark_as_unread" = "ะŸะพะทะฝะฐั‡ะธั‚ะธ ะฝะตะฟั€ะพั‡ะธั‚ะฐะฝะธะผ"; +"screen_roomlist_room_directory_button_title" = "ะŸะตั€ะตะณะปัะฝัƒั‚ะธ ะฒัั– ะบั–ะผะฝะฐั‚ะธ"; "screen_server_confirmation_change_server" = "ะ—ะผั–ะฝะธั‚ะธ ะฟั€ะพะฒะฐะนะดะตั€ะฐ ะพะฑะปั–ะบะพะฒะพะณะพ ะทะฐะฟะธััƒ"; "screen_server_confirmation_message_login_element_dot_io" = "ะŸั€ะธะฒะฐั‚ะฝะธะน ัะตั€ะฒะตั€ ะดะปั ัะฟั–ะฒั€ะพะฑั–ั‚ะฝะธะบั–ะฒ Element."; "screen_server_confirmation_message_login_matrix_dot_org" = "Matrix โ€” ั†ะต ะฒั–ะดะบั€ะธั‚ะฐ ะผะตั€ะตะถะฐ ะดะปั ะฑะตะทะฟะตั‡ะฝะพั—, ะดะตั†ะตะฝั‚ั€ะฐะปั–ะทะพะฒะฐะฝะพั— ะบะพะผัƒะฝั–ะบะฐั†ั–ั—."; @@ -775,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "ะ’ะธ ะทะฑะตั€ะตะณะปะธ ะบะปัŽั‡ ะฒั–ะดะฝะพะฒะปะตะฝะฝั?"; "screen_start_chat_error_starting_chat" = "ะŸั–ะด ั‡ะฐั ัะฟั€ะพะฑะธ ะฟะพั‡ะฐั‚ะธ ั‡ะฐั‚ ัั‚ะฐะปะฐัั ะฟะพะผะธะปะบะฐ"; "screen_view_location_title" = "ะœั–ัั†ะตะทะฝะฐั…ะพะดะถะตะฝะฝั"; -"screen_waitlist_message" = "ะะฐ ั†ะตะน ะผะพะผะตะฝั‚ ั–ัะฝัƒั” ะฒะธัะพะบะธะน ะฟะพะฟะธั‚ ะฝะฐ %1$@ ะฒ %2$@. ะŸะพะฒะตั€ะฝั–ั‚ัŒัั ะดะพ ะทะฐัั‚ะพััƒะฝะบัƒ ั‡ะตั€ะตะท ะบั–ะปัŒะบะฐ ะดะฝั–ะฒ ั– ัะฟั€ะพะฑัƒะนั‚ะต ั‰ะต ั€ะฐะท.\n\nะ”ัะบัƒั”ะผะพ ะทะฐ ั‚ะตั€ะฟั–ะฝะฝั!"; -"screen_waitlist_title" = "ะœะฐะนะถะต ะณะพั‚ะพะฒะพ."; -"screen_waitlist_title_success" = "ะ“ะพั‚ะพะฒะพ."; "screen_welcome_bullet_1" = "ะ”ะทะฒั–ะฝะบะธ, ะพะฟะธั‚ัƒะฒะฐะฝะฝั, ะฟะพัˆัƒะบ ั‚ะพั‰ะพ ะฑัƒะดัƒั‚ัŒ ะดะพะดะฐะฝั– ะฟั–ะทะฝั–ัˆะต ั†ัŒะพะณะพ ั€ะพะบัƒ."; "screen_welcome_bullet_2" = "ะ†ัั‚ะพั€ั–ั ะฟะพะฒั–ะดะพะผะปะตะฝัŒ ะดะปั ะทะฐัˆะธั„ั€ะพะฒะฐะฝะธั… ะบั–ะผะฝะฐั‚ ั‰ะต ะฝะตะดะพัั‚ัƒะฟะฝะฐ."; "screen_welcome_bullet_3" = "ะœะธ ั…ะพั‚ั–ะปะธ ะฑ ะฟะพั‡ัƒั‚ะธ ะฒะฐั, ั€ะพะทะบะฐะถั–ั‚ัŒ ะฝะฐะผ ะฒะฐัˆั– ะฒั€ะฐะถะตะฝะฝั ั‚ะฐ ั–ะดะตั— ั‰ะพะดะพ ะทะฐัั‚ะพััƒะฝะบัƒ ะฝะฐ ัั‚ะพั€ั–ะฝั†ั– ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝัŒ."; @@ -819,7 +880,7 @@ "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_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$@ ะฝะฐ ะฟั€ะธั”ะดะฝะฐะฝะฝั"; @@ -834,6 +895,12 @@ "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$@ ะทะผั–ะฝะธะฒ(-ะปะฐ) ะทะฐะบั€ั–ะฟะปะตะฝั– ะฟะพะฒั–ะดะพะผะปะตะฝะฝั"; +"state_event_room_pinned_events_changed_by_you" = "ะ’ะธ ะทะผั–ะฝะธะปะธ ะทะฐะบั€ั–ะฟะปะตะฝั– ะฟะพะฒั–ะดะพะผะปะตะฝะฝั"; +"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_by_you" = "ะ’ะธ ะฒั–ะดะบั€ั–ะฟะธะปะธ ะฟะพะฒั–ะดะพะผะปะตะฝะฝั"; "state_event_room_reject" = "%1$@ ะฒั–ะดั…ะธะปะธะฒ (-ะปะฐ) ะทะฐะฟั€ะพัˆะตะฝะฝั"; "state_event_room_reject_by_you" = "ะ’ะธ ะฒั–ะดั…ะธะปะธะปะธ ะทะฐะฟั€ะพัˆะตะฝะฝั"; "state_event_room_remove" = "%1$@ ะฒะธะปัƒั‡ะธะฒ (-ะปะฐ) %2$@"; @@ -851,54 +918,54 @@ "state_event_room_unknown_membership_change" = "%1$@ ะฒะฝั–ั (ะฒะฝะตัะปะฐ) ะฝะตะฒั–ะดะพะผั– ะทะผั–ะฝะธ ั‰ะพะดะพ ัะฒะพะณะพ ั‡ะปะตะฝัั‚ะฒะฐ"; "test_language_identifier" = "uk"; "test_untranslated_default_language_identifier" = "en"; -"troubleshoot_notifications_entry_point_section" = "Troubleshoot"; -"troubleshoot_notifications_entry_point_title" = "Troubleshoot notifications"; -"troubleshoot_notifications_screen_action" = "Run tests"; -"troubleshoot_notifications_screen_action_again" = "Run tests again"; -"troubleshoot_notifications_screen_failure" = "Some tests failed. Please check the details."; -"troubleshoot_notifications_screen_notice" = "Run the tests to detect any issue in your configuration that may make notifications not behave as expected."; -"troubleshoot_notifications_screen_quick_fix_action" = "Attempt to fix"; -"troubleshoot_notifications_screen_success" = "All tests passed successfully."; -"troubleshoot_notifications_screen_title" = "Troubleshoot notifications"; -"troubleshoot_notifications_screen_waiting" = "Some tests require your attention. Please check the details."; -"troubleshoot_notifications_test_check_permission_description" = "Check that the application can show notifications."; -"troubleshoot_notifications_test_check_permission_title" = "Check permissions"; -"troubleshoot_notifications_test_current_push_provider_description" = "Get the name of the current provider."; -"troubleshoot_notifications_test_current_push_provider_failure" = "No push providers selected."; -"troubleshoot_notifications_test_current_push_provider_success" = "Current push provider: %1$@."; -"troubleshoot_notifications_test_current_push_provider_title" = "Current push provider"; -"troubleshoot_notifications_test_detect_push_provider_description" = "Ensure that the application has at least one push provider."; -"troubleshoot_notifications_test_detect_push_provider_failure" = "No push providers found."; -"troubleshoot_notifications_test_detect_push_provider_title" = "Detect push providers"; -"troubleshoot_notifications_test_display_notification_description" = "Check that the application can display notification."; -"troubleshoot_notifications_test_display_notification_failure" = "The notification has not been clicked."; +"troubleshoot_notifications_entry_point_section" = "ะฃััƒะฝะตะฝะฝั ะฝะตัะฟั€ะฐะฒะฝะพัั‚ะตะน"; +"troubleshoot_notifications_entry_point_title" = "ะฃััƒะฝะตะฝะฝั ะฝะตะฟะพะปะฐะดะพะบ ัะฟะพะฒั–ั‰ะตะฝัŒ"; +"troubleshoot_notifications_screen_action" = "ะ—ะฐะฟัƒัั‚ะธั‚ะธ ั‚ะตัั‚ะธ"; +"troubleshoot_notifications_screen_action_again" = "ะ—ะฐะฟัƒัั‚ะธั‚ะธ ั‚ะตัั‚ะธ ะทะฝะพะฒัƒ"; +"troubleshoot_notifications_screen_failure" = "ะ”ะตัะบั– ั‚ะตัั‚ะธ ะฝะต ะฟั€ะพะนัˆะปะธ. ะ‘ัƒะดัŒ ะปะฐัะบะฐ, ะฟะตั€ะตะณะปัะฝัŒั‚ะต ะดะตั‚ะฐะปั–."; +"troubleshoot_notifications_screen_notice" = "ะ—ะฐะฟัƒัั‚ั–ั‚ัŒ ั‚ะตัั‚ะธ, ั‰ะพะฑ ะฒะธัะฒะธั‚ะธ ะฑัƒะดัŒ-ัะบัƒ ะฟั€ะพะฑะปะตะผัƒ ัƒ ะฒะฐัˆั–ะน ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ั—, ั‡ะตั€ะตะท ัะบัƒ ัะฟะพะฒั–ั‰ะตะฝะฝั ะผะพะถัƒั‚ัŒ ะฝะต ะฟั€ะฐั†ัŽะฒะฐั‚ะธ ะฝะฐะปะตะถะฝะธะผ ั‡ะธะฝะพะผ."; +"troubleshoot_notifications_screen_quick_fix_action" = "ะกะฟั€ะพะฑัƒะฒะฐั‚ะธ ะฒะธะฟั€ะฐะฒะธั‚ะธ"; +"troubleshoot_notifications_screen_success" = "ะ’ัั– ั‚ะตัั‚ะธ ะฟั€ะพะนัˆะปะธ ัƒัะฟั–ัˆะฝะพ."; +"troubleshoot_notifications_screen_title" = "ะฃััƒะฝะตะฝะฝั ะฝะตะฟะพะปะฐะดะพะบ ัะฟะพะฒั–ั‰ะตะฝัŒ"; +"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_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_display_notification_failure" = "ะ’ะธ ะฝะต ะฝะฐั‚ะธัะฝัƒะปะธ ะฝะฐ ัะฟะพะฒั–ั‰ะตะฝะฝั."; "troubleshoot_notifications_test_display_notification_permission_failure" = "ะะต ะฒะดะฐั”ั‚ัŒัั ะฒั–ะดะพะฑั€ะฐะทะธั‚ะธ ัะฟะพะฒั–ั‰ะตะฝะฝั."; -"troubleshoot_notifications_test_display_notification_success" = "The notification has been clicked!"; -"troubleshoot_notifications_test_display_notification_title" = "Display notification"; -"troubleshoot_notifications_test_display_notification_waiting" = "Please click on the notification to continue the test."; -"troubleshoot_notifications_test_firebase_availability_description" = "Ensure that Firebase is available."; -"troubleshoot_notifications_test_firebase_availability_failure" = "Firebase is not available."; -"troubleshoot_notifications_test_firebase_availability_success" = "Firebase is available."; -"troubleshoot_notifications_test_firebase_availability_title" = "Check Firebase"; -"troubleshoot_notifications_test_firebase_token_description" = "Ensure that Firebase token is available."; -"troubleshoot_notifications_test_firebase_token_failure" = "Firebase token is not known."; -"troubleshoot_notifications_test_firebase_token_success" = "Firebase token: %1$@."; -"troubleshoot_notifications_test_firebase_token_title" = "Check Firebase token"; -"troubleshoot_notifications_test_push_loop_back_description" = "Ensure that the application is receiving push."; -"troubleshoot_notifications_test_push_loop_back_failure_1" = "Error: pusher has rejected the request."; -"troubleshoot_notifications_test_push_loop_back_failure_2" = "Error: %1$@."; -"troubleshoot_notifications_test_push_loop_back_failure_3" = "Error, cannot test push."; +"troubleshoot_notifications_test_display_notification_success" = "ะ’ะธ ะฝะฐั‚ะธัะฝัƒะปะธ ะฝะฐ ัะฟะพะฒั–ั‰ะตะฝะฝั!"; +"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 ะดะพัั‚ัƒะฟะฝะธะน."; +"troubleshoot_notifications_test_firebase_availability_title" = "ะŸะตั€ะตะฒั–ั€ะบะฐ Firebase"; +"troubleshoot_notifications_test_firebase_token_description" = "ะŸะตั€ะตะบะพะฝัƒั”ั‚ัŒัั, ั‰ะพ ั‚ะพะบะตะฝ Firebase ะดะพัั‚ัƒะฟะฝะธะน."; +"troubleshoot_notifications_test_firebase_token_failure" = "ะขะพะบะตะฝ Firebase ะฝะตะฒั–ะดะพะผะธะน."; +"troubleshoot_notifications_test_firebase_token_success" = "ะขะพะบะตะฝ Firebase: %1$@."; +"troubleshoot_notifications_test_firebase_token_title" = "ะŸะตั€ะตะฒั–ั€ะบะฐ ั‚ะพะบะตะฝะฐ Firebase"; +"troubleshoot_notifications_test_push_loop_back_description" = "ะŸะตั€ะตะบะพะฝัƒั”ั‚ัŒัั, ั‰ะพ ะทะฐัั‚ะพััƒะฝะพะบ ะพั‚ั€ะธะผัƒั” push-ัะฟะพะฒั–ั‰ะตะฝะฝั."; +"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_title" = "Test Push loop back"; -"troubleshoot_notifications_test_unified_push_description" = "Ensure that UnifiedPush distributors are available."; -"troubleshoot_notifications_test_unified_push_failure" = "No push distributors found."; -"troubleshoot_notifications_test_unified_push_title" = "Check UnifiedPush"; +"troubleshoot_notifications_test_push_loop_back_title" = "ะŸะตั€ะตะฒั–ั€ะบะฐ ะทะฒะพั€ะพั‚ะฝะพะณะพ ะฝะฐะดัะธะปะฐะฝะฝั"; +"troubleshoot_notifications_test_unified_push_description" = "ะŸะตั€ะตะบะพะฝัƒั”ั‚ัŒัั, ั‰ะพ ะดะธัั‚ั€ะธะฑ'ัŽั‚ะพั€ะธ UnifiedPush ะดะพัั‚ัƒะฟะฝั–."; +"troubleshoot_notifications_test_unified_push_failure" = "ะ”ะธัั‚ั€ะธะฑ'ัŽั‚ะพั€ั–ะฒ ะฝะต ะทะฝะฐะนะดะตะฝะพ."; +"troubleshoot_notifications_test_unified_push_title" = "ะŸะตั€ะตะฒั–ั€ะบะฐ UnifiedPush"; "dialog_title_error" = "ะŸะพะผะธะปะบะฐ"; "dialog_title_success" = "ะฃัะฟั–ั…"; "notification_fallback_content" = "ะกะฟะพะฒั–ั‰ะตะฝะฝั"; "notification_invitation_action_join" = "ะ”ะพั”ะดะฝะฐั‚ะธัั"; -"notification_room_action_mark_as_read" = "ะŸะพะทะฝะฐั‡ะธั‚ะธ ัะบ ะฟั€ะพั‡ะธั‚ะฐะฝะต"; +"notification_room_action_mark_as_read" = "ะŸะพะทะฝะฐั‡ะธั‚ะธ ะฟั€ะพั‡ะธั‚ะฐะฝะธะผ"; "notification_room_action_quick_reply" = "ะจะฒะธะดะบะฐ ะฒั–ะดะฟะพะฒั–ะดัŒ"; "screen_room_mentions_at_room_title" = "ะฃัั–"; "screen_account_provider_signin_subtitle" = "ะขัƒั‚ ะฑัƒะดัƒั‚ัŒ ะทะฑะตั€ั–ะณะฐั‚ะธัั ะ’ะฐัˆั– ั€ะพะทะผะพะฒะธ - ั‚ะฐะบ ัะฐะผะพ, ัะบ ะ’ะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะฟะพัˆั‚ะพะฒัƒ ัะบั€ะธะฝัŒะบัƒ ะดะปั ะทะฑะตั€ั–ะณะฐะฝะฝั ัะฒะพั—ั… ะตะปะตะบั‚ั€ะพะฝะฝะธั… ะปะธัั‚ั–ะฒ."; @@ -921,6 +988,7 @@ "screen_dm_details_unblock_user" = "ะ ะพะทะฑะปะพะบัƒะฒะฐั‚ะธ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ"; "screen_edit_poll_delete_confirmation_title" = "ะ’ะธะดะฐะปะธั‚ะธ ะพะฟะธั‚ัƒะฒะฐะฝะฝั"; "screen_edit_poll_title" = "ะ ะตะดะฐะณัƒะฒะฐั‚ะธ ะพะฟะธั‚ัƒะฒะฐะฝะฝั"; +"screen_identity_use_another_device" = "Use another device"; "screen_login_subtitle" = "Matrix โ€” ั†ะต ะฒั–ะดะบั€ะธั‚ะฐ ะผะตั€ะตะถะฐ ะดะปั ะฑะตะทะฟะตั‡ะฝะพั—, ะดะตั†ะตะฝั‚ั€ะฐะปั–ะทะพะฒะฐะฝะพั— ะบะพะผัƒะฝั–ะบะฐั†ั–ั—."; "screen_qr_code_login_invalid_scan_state_retry_button" = "ะกะฟั€ะพะฑัƒะนั‚ะต ั‰ะต ั€ะฐะท"; "screen_report_content_block_user" = "ะ—ะฐะฑะปะพะบัƒะฒะฐั‚ะธ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "ะ’ะธะนั‚ะธ"; "screen_signout_confirmation_dialog_title" = "ะ’ะธะนั‚ะธ"; "screen_signout_preference_item" = "ะ’ะธะนั‚ะธ"; -"screen_waitlist_message_success" = "ะ›ะฐัะบะฐะฒะพ ะฟั€ะพัะธะผะพ ะดะพ %1$@!"; diff --git a/ElementX/Resources/Localizations/uk.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/uk.lproj/Localizable.stringsdict index dcaaddcb9f..a9a812c7bb 100644 --- a/ElementX/Resources/Localizations/uk.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/uk.lproj/Localizable.stringsdict @@ -218,6 +218,22 @@ ะฅะธะฑะฝะธะน PIN-ะบะพะด. ะ’ะธ ะผะฐั”ั‚ะต ั‰ะต %1$d ัˆะฐะฝัั–ะฒ + 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 @@ -319,9 +335,11 @@ NSStringFormatValueTypeKey d one - Found %1$d push provider: %2$@ - other - Found %1$d push providers: %2$@ + ะ’ะธัะฒะปะตะฝะพ %1$d ะฟะพัั‚ะฐั‡ะฐะปัŒะฝะธะบะฐ: %2$@ + few + ะ’ะธัะฒะปะตะฝะพ %1$d ะฟะพัั‚ะฐั‡ะฐะปัŒะฝะธะบั–ะฒ: %2$@ + many + ะ’ะธัะฒะปะตะฝะพ %1$d ะฟะพัั‚ะฐั‡ะฐะปัŒะฝะธะบั–ะฒ: %2$@ troubleshoot_notifications_test_unified_push_success @@ -335,9 +353,11 @@ NSStringFormatValueTypeKey d one - %1$d distributor found: %2$@. - other - %1$d distributors found: %2$@. + %1$d ะดะธัั‚ั€ะธะฑ'ัŽั‚ะพั€ะฐ ะทะฝะฐะนะดะตะฝะพ: %2$@. + few + %1$d ะดะธัั‚ั€ะธะฑ'ัŽั‚ะพั€ั–ะฒ ะทะฝะฐะนะดะตะฝะพ: %2$@. + many + %1$d ะดะธัั‚ั€ะธะฑ'ัŽั‚ะพั€ั–ะฒ ะทะฝะฐะนะดะตะฝะพ: %2$@. diff --git a/ElementX/Resources/Localizations/uz.lproj/Localizable.strings b/ElementX/Resources/Localizations/uz.lproj/Localizable.strings new file mode 100644 index 0000000000..7a9d54d95a --- /dev/null +++ b/ElementX/Resources/Localizations/uz.lproj/Localizable.strings @@ -0,0 +1,1015 @@ +"Notification" = "Bildirishnoma"; +"a11y_delete" = "Oสปchirish"; +"a11y_hide_password" = "Parolni yashirish"; +"a11y_jump_to_bottom" = "Jump to bottom"; +"a11y_notifications_mentions_only" = "Faqat eslatmalar"; +"a11y_notifications_muted" = "Ovozsiz"; +"a11y_page_n" = "Page %1$d"; +"a11y_pause" = "Pauza"; +"a11y_pin_field" = "PIN field"; +"a11y_play" = "O'ynang"; +"a11y_poll" = "So'ro'vnoma"; +"a11y_poll_end" = "Soโ€˜rovnoma yakunlandi"; +"a11y_react_with" = "React with %1$@"; +"a11y_react_with_other_emojis" = "React with other emojis"; +"a11y_read_receipts_multiple" = "Read by %1$@ and %2$@"; +"a11y_read_receipts_single" = "Read by %1$@"; +"a11y_read_receipts_tap_to_show_all" = "Tap to show all"; +"a11y_remove_reaction_with" = "Remove reaction with %1$@"; +"a11y_send_files" = "Fayllarni yuborish"; +"a11y_show_password" = "Parolni ko'rsatish"; +"a11y_start_call" = "Start a call"; +"a11y_user_menu" = "Foydalanuvchi menyusi"; +"a11y_voice_message_record" = "Ovoz yozishni amalga oshiring"; +"a11y_voice_message_stop_recording" = "Stop recording"; +"action_accept" = "Qabul qiling"; +"action_add_to_timeline" = "Vaqt jadvaliga qo'shing"; +"action_back" = "Orqaga"; +"action_call" = "Call"; +"action_cancel" = "Bekor qilish"; +"action_cancel_for_now" = "Cancel for now"; +"action_choose_photo" = "Fotosuratni tanlang"; +"action_clear" = "Tozalash"; +"action_close" = "Yopish"; +"action_complete_verification" = "To'liq tekshirish"; +"action_confirm" = "Tasdiqlash"; +"action_confirm_password" = "Confirm password"; +"action_continue" = "Davom etish"; +"action_copy" = "nusxa"; +"action_copy_link" = "Havolani nusxalash"; +"action_copy_link_to_message" = "Havolani xabaraga nusxalash"; +"action_create" = "Yaratmoq"; +"action_create_a_room" = "Xonani yaratish"; +"action_deactivate" = "Deactivate"; +"action_decline" = "Rad etish"; +"action_delete_poll" = "Delete Poll"; +"action_disable" = "Oสปchirish"; +"action_discard" = "Discard"; +"action_done" = "Bajarildi"; +"action_edit" = "Tahrirlash"; +"action_edit_poll" = "Soโ€˜rovnomani tahrirlash"; +"action_enable" = "Yoqish"; +"action_end_poll" = "Soโ€˜rovnomani tugatish"; +"action_enter_pin" = "Enter PIN"; +"action_forgot_password" = "Parolni unutdingizmi?"; +"action_forward" = "Oldinga"; +"action_go_back" = "Go back"; +"action_invite" = "Taklif qilish"; +"action_invite_friends" = "Odamlarni taklif qiling"; +"action_invite_friends_to_app" = "Odamlarni taklif qilish%1$@"; +"action_invite_people_to_app" = "Odamlarni taklif qiling%1$@"; +"action_invites_list" = "Takliflar"; +"action_join" = "Qo'shilish"; +"action_learn_more" = "Batafsil malumot"; +"action_leave" = "Tark etish"; +"action_leave_conversation" = "Leave conversation"; +"action_leave_room" = "Xonani tark etish"; +"action_manage_account" = "Hisobni boshqarish"; +"action_manage_devices" = "Qurilmalarni boshqarish"; +"action_message" = "Message"; +"action_next" = "Keyingisi"; +"action_no" = "Yo'q"; +"action_not_now" = "Hozir emas"; +"action_ok" = "Ok"; +"action_open_settings" = "Sozlamalar"; +"action_open_with" = "Bilan oching"; +"action_pin" = "Pin"; +"action_quick_reply" = "Tez javob"; +"action_quote" = "Iqtibos"; +"action_react" = "Reaksiya qilish"; +"action_reject" = "Reject"; +"action_remove" = "Ochirish"; +"action_reply" = "Javob bering"; +"action_reply_in_thread" = "Mavzuda javob bering"; +"action_report_bug" = "Xato haqida xabar berish"; +"action_report_content" = "Tarkib haqida xabar berish"; +"action_reset" = "Reset"; +"action_reset_identity" = "Reset identity"; +"action_retry" = "Qayta urinish"; +"action_retry_decryption" = "Shifrni ochishni qayta urinish"; +"action_save" = "Saqlash"; +"action_search" = "Qidirmoq"; +"action_send" = "Yuborish"; +"action_send_message" = "Xabar yuborish"; +"action_share" = "Ulashish"; +"action_share_link" = "Havolani ulashing"; +"action_sign_in_again" = "Qaytadan kiring"; +"action_signout" = "Tizimdan chiqish"; +"action_signout_anyway" = "Baribir tizimdan chiqing"; +"action_skip" = "Oสปtkazib yuborish"; +"action_start" = "Boshlash"; +"action_start_chat" = "Suhbatni boshlash"; +"action_start_verification" = "Tasdiqlashni boshlang"; +"action_static_map_load" = "Xaritani yuklash uchun bosing"; +"action_take_photo" = "Rasmga olmoq"; +"action_tap_for_options" = "Tap for options"; +"action_try_again" = "Try again"; +"action_unpin" = "Unpin"; +"action_view_in_timeline" = "View in timeline"; +"action_view_source" = "Manbani korish"; +"action_yes" = "Ha"; +"action.load_more" = "Load more"; +"action_deactivate_account" = "Deactivate account"; +"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" = "Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices."; +"banner.set_up_recovery.title" = "Set up recovery"; +"common_about" = "Haqida"; +"common_acceptable_use_policy" = "Qabul qilinadigan foydalanish siyosati"; +"common_advanced_settings" = "Kengaytirilgan sozlamalar"; +"common_analytics" = "Analitika"; +"common_appearance" = "Appearance"; +"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"; +"common_creating_room" = "Xona yaratilmoqdaโ€ฆ"; +"common_current_user_left_room" = "Xonani tark etdi"; +"common_dark" = "Dark"; +"common_decryption_error" = "Shifrni ochish xatosi"; +"common_developer_options" = "Dasturchi variantlari"; +"common_direct_chat" = "Direct chat"; +"common_edited_suffix" = "(tahrirlangan)"; +"common_editing" = "Tahrirlash"; +"common_emote" = "*%1$@%2$@"; +"common_encryption_enabled" = "Shifrlash yoqilgan"; +"common_enter_your_pin" = "Enter your PIN"; +"common_error" = "Xato"; +"common_everyone" = "Har kim"; +"common_face_id_ios" = "Face ID"; +"common_failed" = "Failed"; +"common_favourite" = "Favourite"; +"common_favourited" = "Favourited"; +"common_file" = "Fayl"; +"common_forward_message" = "Xabarni yo'naltirish"; +"common_gif" = ""; +"common_image" = "Surat"; +"common_in_reply_to" = "%1$@ga Javob bering"; +"common_invite_unknown_profile" = "Ushbu Matrix identifikatori topilmadi, shuning uchun taklif qabul qilinmasligi mumkin."; +"common_leaving_room" = "Xonadan chiqish"; +"common_light" = "Light"; +"common_link_copied_to_clipboard" = "Havola vaqtinchalik xotiraga nusxalandi"; +"common_loading" = "Yuklanmoqdaโ€ฆ"; +"common_message" = "Xabar"; +"common_message_actions" = "Message actions"; +"common_message_layout" = "Xabar tartibi"; +"common_message_removed" = "Xabar ochirib tashlandi"; +"common_modern" = "Zamonaviy"; +"common_mute" = "Ovozsiz qilish"; +"common_no_results" = "Natijalar yoสปq"; +"common_offline" = "Oflayn"; +"common_optic_id_ios" = "Optic ID"; +"common_or" = "or"; +"common_password" = "Parol"; +"common_people" = "Odamlar"; +"common_permalink" = "Doimiy havola"; +"common_permission" = "Ruxsat"; +"common_please_wait" = "Please waitโ€ฆ"; +"common_poll_total_votes" = "Jami ovozlar:%1$@"; +"common_poll_undisclosed_text" = "Natijalar soสปrovnoma tugagandan soสปng koสปrsatiladi"; +"common_privacy_policy" = "Maxfiylik siyosati"; +"common_reaction" = "Reaktsiya"; +"common_reactions" = "reaksiyalar"; +"common_recovery_key" = "Qayta tiklash kaliti"; +"common_refreshing" = "Yangilanmoqdaโ€ฆ"; +"common_replying_to" = "%1$@ga Javob berilmoqda"; +"common_report_a_bug" = "Xato haqida xabar bering"; +"common_report_a_problem" = "Report a problem"; +"common_report_submitted" = "Hisobot topshirildi"; +"common_rich_text_editor" = "Boy matn muharriri"; +"common_room" = "Room"; +"common_room_name" = "Xona nomi"; +"common_room_name_placeholder" = "masalan, loyihangiz nomi"; +"common_saved_changes" = "Saved changes"; +"common_saving" = "Saving"; +"common_screen_lock" = "Screen lock"; +"common_search_for_someone" = "Kimnidir qidiring"; +"common_search_results" = "Qidiruv natijalari"; +"common_security" = "Xavfsizlik"; +"common_seen_by" = "Seen by"; +"common_sending" = "Yuborilmoqdaโ€ฆ"; +"common_sending_failed" = "Sending failed"; +"common_sent" = "Sent"; +"common_server_not_supported" = "Server qo'llab-quvvatlanmaydi"; +"common_server_url" = "Server URL manzili"; +"common_settings" = "Sozlamalar"; +"common_shared_location" = "Joylashuvi ulashildi"; +"common_signing_out" = "Signing out"; +"common_starting_chat" = "Chat boshlanmoqdaโ€ฆ"; +"common_sticker" = "Stiker"; +"common_success" = "Muvaffaqiyat"; +"common_suggestions" = "Tavsiyalar"; +"common_syncing" = "Sinxronlash"; +"common_system" = "System"; +"common_text" = "Matn"; +"common_third_party_notices" = "Uchinchi tomon bildirishnomalari"; +"common_thread" = "Ip"; +"common_topic" = "Mavzu"; +"common_topic_placeholder" = "Bu xona nima haqida?"; +"common_touch_id_ios" = "Touch ID"; +"common_unable_to_decrypt" = "Shifrni ochish imkonsiz"; +"common_unable_to_invite_message" = "Takliflarni bir yoki bir nechta foydalanuvchiga yuborib boโ€˜lmadi."; +"common_unable_to_invite_title" = "Taklif(lar)ni yuborib boโ€˜lmadi"; +"common_unlock" = "Unlock"; +"common_unmute" = "Ovozni yoqish"; +"common_unsupported_event" = "Qo'llab-quvvatlanmagan hodisa"; +"common_username" = "Foydalanuvchi nomi"; +"common_verification_cancelled" = "Tasdiqlash bekor qilindi"; +"common_verification_complete" = "Tasdiqlash yakunlandi"; +"common_video" = "Video"; +"common_voice_message" = "Ovozli xabar"; +"common_waiting" = "Kutilmoqdaโ€ฆ"; +"common_waiting_for_decryption_key" = "Waiting for this message"; +"common.do_not_show_this_again" = "Do not show this again"; +"common.open_source_licenses" = "Open source licenses"; +"common.pinned" = "Pinned"; +"common.send_to" = "Send to"; +"common_no_room_name" = "No room name"; +"common_poll_end_confirmation" = "Haqiqatan ham bu soสปrovnomani tugatmoqchimisiz?"; +"common_poll_summary" = "Soโ€˜rov:%1$@"; +"common_something_went_wrong" = "Something went wrong"; +"common_unable_to_decrypt_no_access" = "You don't have access to this message"; +"common_verify_device" = "Verify device"; +"confirm_recovery_key_banner_message" = "Your chat backup is currently out of sync. You need to enter your recovery key to maintain access to your chat backup."; +"confirm_recovery_key_banner_title" = "Enter your recovery key"; +"crash_detection_dialog_content" = "%1$@oxirgi marta ishlatilganda qulab tushdi. Biz bilan nosozlik hisobotini baham ko'rmoqchimisiz?"; +"dialog_permission_camera" = "Ilovaga kameradan foydalanishiga ruxsat berish uchun tizim sozlamalarida ruxsat bering."; +"dialog_permission_generic" = "Iltimos, tizim sozlamalarida ruxsat bering."; +"dialog_permission_location_description_ios" = "Grant access in Settings -> Location."; +"dialog_permission_location_title_ios" = "%1$@ does not have access to your location."; +"dialog_permission_microphone" = "Ilovaga mikrofondan foydalanishiga ruxsat berish uchun tizim sozlamalarida ruxsat bering."; +"dialog_permission_microphone_description_ios" = "Grant access so you can record and send messages with audio."; +"dialog_permission_microphone_title_ios" = "%1$@ needs permission to access your microphone."; +"dialog_permission_notification" = "Ilova bildirishnomalarni ko'rsatishi uchun tizim sozlamalarida ruxsat bering."; +"dialog_title_confirmation" = "Tasdiqlash"; +"dialog_title_warning" = "Ogohlantirish"; +"dialog_unsaved_changes_description_ios" = "Your changes wonโ€™t be saved"; +"dialog_unsaved_changes_title" = "Save changes?"; +"emoji_picker_category_activity" = "Faoliyatlar"; +"emoji_picker_category_flags" = "Bayroqlar"; +"emoji_picker_category_foods" = "Oziq-ovqat va ichimliklar"; +"emoji_picker_category_nature" = "Hayvonlar va tabiat"; +"emoji_picker_category_objects" = "Ob'ektlar"; +"emoji_picker_category_people" = "Smayllar va odamlar"; +"emoji_picker_category_places" = "Sayohat va Joylar"; +"emoji_picker_category_symbols" = "Belgilar"; +"error_account_creation_not_possible" = "Your homeserver needs to be upgraded to support Matrix Authentication Service and account creation."; +"error_failed_creating_the_permalink" = "Doimiy havola yaratilmadi"; +"error_failed_loading_map" = "%1$@xaritani yuklay olmadi. Iltimos keyinroq qayta urinib ko'ring."; +"error_failed_loading_messages" = "Xabarlar yuklanmadi"; +"error_failed_locating_user" = "%1$@joylashuvingizga kira olmadi. Iltimos keyinroq qayta urinib ko'ring."; +"error_failed_uploading_voice_message" = "Failed to upload your voice message."; +"error_message_not_found" = "Message not found"; +"error_no_compatible_app_found" = "Bu amalni bajarish uchun mos ilova topilmadi."; +"error_some_messages_have_not_been_sent" = "Bazi xabarlar yuborilmagan"; +"error_unknown" = "Kechirasiz, xatolik yuz berdi"; +"event_shield_reason_authenticity_not_guaranteed" = "The authenticity of this encrypted message can't be guaranteed on this device."; +"event_shield_reason_previously_verified" = "Encrypted by a previously-verified user."; +"event_shield_reason_sent_in_clear" = "Not encrypted."; +"event_shield_reason_unknown_device" = "Encrypted by an unknown or deleted device."; +"event_shield_reason_unsigned_device" = "Encrypted by a device not verified by its owner."; +"event_shield_reason_unverified_identity" = "Encrypted by an unverified user."; +"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_title" = "Enhance your call experience"; +"invite_friends_rich_title" = "๐Ÿ”๏ธ Menga qo'shiling%1$@"; +"invite_friends_text" = "Hey, men bilan gaplash%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_room_alert_empty_subtitle" = "Bu xonani tark etmoqchi ekanligingizga ishonchingiz komilmi? Siz bu yerda yagona odamsiz. Agar siz tark etsangiz, kelajakda hech kim qo'shila olmaydi, jumladan siz ham."; +"leave_room_alert_private_subtitle" = "Bu xonani tark etmoqchi ekanligingizga ishonchingiz komilmi? Bu xona ochiq emas va siz taklifsiz qayta qoโ€˜shila olmaysiz."; +"leave_room_alert_subtitle" = "Xonani tark etmoqchi ekanligingizga ishonchingiz komilmi?"; +"login_initial_device_name_ios" = "%1$@iOS"; +"notification_channel_call" = "Qo'ng'iroq"; +"notification_channel_listening_for_events" = "Voqealarni tinglash"; +"notification_channel_noisy" = "Shovqinli bildirishnomalar"; +"notification_channel_ringing_calls" = "Ringing calls"; +"notification_channel_silent" = "Ovozsiz bildirishnomalar"; +"notification_incoming_call" = "Incoming call"; +"notification_inline_reply_failed" = "** Yuborilmadi - iltimos, xonani oching"; +"notification_invitation_action_reject" = "Rad etish"; +"notification_invite_body" = "Sizni suhbatga taklif qildi"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; +"notification_mentioned_you_body" = "Mentioned you: %1$@"; +"notification_new_messages" = "Yangi xabarlar"; +"notification_reaction_body" = "%1$@bilan munosabat bildiring"; +"notification_room_invite_body" = "Sizni xonaga kirishga taklif qildi"; +"notification_room_invite_body_with_sender" = "%1$@ invited you to join the room"; +"notification_sender_me" = "Men"; +"notification_sender_mention_reply" = "%1$@ mentioned or replied"; +"notification_test_push_notification_content" = "Siz bildirishnomani ko'ryapsiz! Meni bosing!"; +"notification_ticker_text_dm" = "%1$@:%2$@"; +"notification_ticker_text_group" = "%1$@:%2$@%3$@"; +"notification_unread_notified_messages_and_invitation" = "%1$@va%2$@"; +"notification_unread_notified_messages_in_room" = "%1$@ichida%2$@"; +"notification_unread_notified_messages_in_room_and_invitation" = "%1$@ichida%2$@ va%3$@"; +"preference_rageshake" = "Xato haqida xabar berish uchun G'azablanish"; +"rageshake_detection_dialog_content" = "Siz hafsalasi pir bo'lib telefonni silkitayotganga o'xshaysiz. Xatolar haqida hisobot ekranini ochmoqchimisiz?"; +"rich_text_editor_bullet_list" = "Belgilar roสปyxatini almashtirish"; +"rich_text_editor_close_formatting_options" = "Formatlash parametrlarini yoping"; +"rich_text_editor_code_block" = "Kod blokini almashtirish"; +"rich_text_editor_composer_placeholder" = "Xabarโ€ฆ"; +"rich_text_editor_create_link" = "Havola yarating"; +"rich_text_editor_edit_link" = "Havolani tahrirlash"; +"rich_text_editor_format_bold" = "Qalin formatni qo'llang"; +"rich_text_editor_format_italic" = "Kursiv formatini qo'llang"; +"rich_text_editor_format_strikethrough" = "Chizilgan formatni qo'llash"; +"rich_text_editor_format_underline" = "Pastki chiziq formatini qo'llang"; +"rich_text_editor_full_screen_toggle" = "Toสปliq ekran rejimiga oสปtish"; +"rich_text_editor_indent" = "Paragraf"; +"rich_text_editor_inline_code" = "Koq formatini mos ravishda qo'shing"; +"rich_text_editor_link" = "Havolani o'rnatish"; +"rich_text_editor_numbered_list" = "Raqamlangan roสปyxatni almashtirish"; +"rich_text_editor_open_compose_options" = "Yozish parametrlarini oching"; +"rich_text_editor_quote" = "Iqtibosni almashtirish"; +"rich_text_editor_remove_link" = "Havolani olib tashlang"; +"rich_text_editor_unindent" = "Paragrafni bekor qilish"; +"rich_text_editor_url_placeholder" = "Havola"; +"rich_text_editor_a11y_add_attachment" = "Biriktirma qo'shing"; +"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_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_pinned_timeline_screen_title_empty" = "Pinned messages"; +"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" = "Notify the whole room"; +"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_details_pinned_events_row_title" = "Pinned messages"; +"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_account_provider_change" = "Hisob provayderini o'zgartiring"; +"screen_account_provider_form_hint" = "Uy server manzili"; +"screen_account_provider_form_notice" = "Qidiruv so'zini yoki domen manzilini kiriting."; +"screen_account_provider_form_subtitle" = "Kompaniya, jamoa yoki shaxsiy serverni qidiring."; +"screen_account_provider_form_title" = "Hisob provayderini toping"; +"screen_account_provider_signin_title" = "Siz %@ga kirmoqchisiz"; +"screen_account_provider_signup_title" = "Siz %@da hisob yaratmoqchisiz"; +"screen_advanced_settings_developer_mode" = "Dasturchi rejimi"; +"screen_advanced_settings_developer_mode_description" = "Ishlab chiquvchilar uchun xususiyatlar va funksiyalarga kirishni yoqing."; +"screen_advanced_settings_rich_text_editor_description" = "Boy matn muharriri o'chiring Markdown bilan qo'lda yozish uchun"; +"screen_advanced_settings_send_read_receipts" = "Read receipts"; +"screen_advanced_settings_send_read_receipts_description" = "If turned off, your read receipts won't be sent to anyone. You will still receive read receipts from other users."; +"screen_advanced_settings_share_presence" = "Share presence"; +"screen_advanced_settings_share_presence_description" = "If turned off, you wonโ€™t be able to send or receive read receipts or typing notifications."; +"screen_advanced_settings_view_source_description" = "Enable option to view message source in the timeline."; +"screen_analytics_prompt_data_usage" = "Biz hech qanday shaxsiy ma'lumotlarni yozmaymiz yoki profilga kiritmaymiz"; +"screen_analytics_prompt_help_us_improve" = "Muammolarni aniqlashda yordam berish uchun anonim foydalanish maสผlumotlarini baham koสปring."; +"screen_analytics_prompt_read_terms" = "Siz bizning barcha shartlarimizni o'qishingiz mumkin%1$@."; +"screen_analytics_prompt_read_terms_content_link" = "Bu yerga"; +"screen_analytics_prompt_settings" = "Buni istalgan vaqtda oสปchirib qoสปyishingiz mumkin"; +"screen_analytics_prompt_third_party_sharing" = "Biz sizning ma'lumotlaringizni uchinchi tomonlar bilan baham ko'rmaymiz"; +"screen_analytics_prompt_title" = "Yaxshilashga yordam bering%1$@"; +"screen_analytics_settings_share_data" = "Analitik ma'lumotlarni ulashish"; +"screen_app_lock_biometric_authentication" = "biometric authentication"; +"screen_app_lock_biometric_unlock" = "biometric unlock"; +"screen_app_lock_biometric_unlock_reason_ios" = "Authentication is needed to access your app"; +"screen_app_lock_forgot_pin" = "Forgot PIN?"; +"screen_app_lock_settings_change_pin" = "Change PIN code"; +"screen_app_lock_settings_enable_biometric_unlock" = "Allow biometric unlock"; +"screen_app_lock_settings_enable_face_id_ios" = "Allow Face ID"; +"screen_app_lock_settings_enable_optic_id_ios" = "Allow Optic ID"; +"screen_app_lock_settings_enable_touch_id_ios" = "Allow Touch ID"; +"screen_app_lock_settings_remove_pin" = "Remove PIN"; +"screen_app_lock_settings_remove_pin_alert_message" = "Are you sure you want to remove PIN?"; +"screen_app_lock_settings_remove_pin_alert_title" = "Remove PIN?"; +"screen_app_lock_setup_biometric_unlock_allow_title" = "Allow %1$@"; +"screen_app_lock_setup_biometric_unlock_skip" = "Iโ€™d rather use PIN"; +"screen_app_lock_setup_biometric_unlock_subtitle" = "Save yourself some time and use %1$@ to unlock the app each time"; +"screen_app_lock_setup_choose_pin" = "Choose PIN"; +"screen_app_lock_setup_confirm_pin" = "Confirm PIN"; +"screen_app_lock_setup_pin_context" = "Lock %1$@ to add extra security to your chats.\n\nChoose something memorable. If you forget this PIN, you will be logged out of the app."; +"screen_app_lock_setup_pin_forbidden_dialog_content" = "You cannot choose this as your PIN code for security reasons"; +"screen_app_lock_setup_pin_forbidden_dialog_title" = "Choose a different PIN"; +"screen_app_lock_setup_pin_mismatch_dialog_content" = "Please enter the same PIN twice"; +"screen_app_lock_setup_pin_mismatch_dialog_title" = "PINs don't match"; +"screen_app_lock_signout_alert_message" = "Youโ€™ll need to re-login and create a new PIN to proceed"; +"screen_app_lock_signout_alert_title" = "You are being signed out"; +"screen_blocked_users_empty" = "You have no blocked users"; +"screen_blocked_users_unblocking" = "Unblockingโ€ฆ"; +"screen_bug_report_attach_screenshot" = "Ekran tasvirini biriktirish"; +"screen_bug_report_contact_me" = "Agar sizda keyingi savollar bo'lsa, men bilan bog'lanishingiz mumkin."; +"screen_bug_report_contact_me_title" = "Men bilan bog'laning"; +"screen_bug_report_edit_screenshot" = "Ekran tasvirini tahrirlash"; +"screen_bug_report_editor_description" = "Iltimos, muammoni tasvirlab bering. Nima qildingiz? Nima bo'lishini kutgan edingiz? Aslida nima bo'ldi. Iltimos, iloji boricha batafsilroq ma'lumot bering."; +"screen_bug_report_editor_placeholder" = "Muammoni tasvirlab beringโ€ฆ"; +"screen_bug_report_editor_supporting" = "Iloji bo'lsa, tavsifni ingliz tilida yozing."; +"screen_bug_report_error_description_too_short" = "The description is too short, please provide more details about what happened. Thanks!"; +"screen_bug_report_include_crash_logs" = "Buzilish jurnallarini yuboring"; +"screen_bug_report_include_logs" = "Jurnallarga ruxsat bering"; +"screen_bug_report_include_screenshot" = "Ekran tasvirini yuboring"; +"screen_bug_report_logs_description" = "Har bir narsa to'ri ishlayotganiga ishonch hosil qilish uchun xabaringizga jurnallar kiritiladi. Xabarni jurnallarsiz yuborish uchun ushbu sozlamani oสปchiring."; +"screen_bug_report_view_logs" = "View logs"; +"screen_change_account_provider_matrix_org_subtitle" = "Matrix.org - bu Matrix.org Jamg'armasi tomonidan boshqariladigan xavfsiz, markazlashtirilmagan aloqa uchun ommaviy Matrix tarmog'idagi katta, bepul server."; +"screen_change_account_provider_other" = "Boshqa"; +"screen_change_account_provider_subtitle" = "Shaxsiy serveringiz yoki ishchi hisob qaydnomangiz kabi boshqa hisob provayderidan foydalaning."; +"screen_change_account_provider_title" = "Hisob provayderini o'zgartiring"; +"screen_change_server_error_invalid_homeserver" = "Bu uy serveriga kira olmadik. Iltimos, uy serverining URL manzilini to'ri kiritganingizni tekshiring. Agar URL toสปgสปri boสปlsa, qoสปshimcha yordam olish uchun uy serveri administratoriga murojaat qiling."; +"screen_change_server_error_invalid_well_known" = "Sliding sync isn't available due to an issue in the well-known file:\n%1$@"; +"screen_change_server_error_no_sliding_sync_message" = "Hozirda bu server siljish sinxronlashni qoโ€˜llab-quvvatlamaydi."; +"screen_change_server_form_header" = "Uy serverining URL manzili"; +"screen_change_server_form_notice" = "Siz faqat siljish sinxronlashni qo'llab-quvvatlaydigan mavjud serverga ulanishingiz mumkin. Uy serveringiz administratori uni sozlashi kerak.%1$@"; +"screen_change_server_subtitle" = "Serveringizning manzili nima?"; +"screen_change_server_title" = "Serveringizni tanlang"; +"screen_chat_backup_key_backup_action_disable" = "Zaxiralashni o'chirib qo'ying"; +"screen_chat_backup_key_backup_action_enable" = "Zaxiralashni yoqing"; +"screen_chat_backup_key_backup_description" = "Zaxiralash xabarlar tarixini yo'qotmaslikni ta'minlaydi.%1$@."; +"screen_chat_backup_key_backup_title" = "Zaxira"; +"screen_chat_backup_recovery_action_change" = "Qayta tiklash kalitini o'zgartiring"; +"screen_chat_backup_recovery_action_confirm" = "Qayta tiklash kalitini kiriting"; +"screen_chat_backup_recovery_action_confirm_description" = "Sizning chat zaxirangiz hozirda sinxronlashtirilmagan."; +"screen_chat_backup_recovery_action_setup" = "Qayta tiklashni sozlang"; +"screen_chat_backup_recovery_action_setup_description" = "Agar barcha qurilmalaringizni yoโ€˜qotib qoโ€˜ysangiz yoki tizimdan chiqqan boโ€˜lsangiz, shifrlangan xabarlaringizga ruxsat oling%1$@ hamma joyda."; +"screen_create_account_title" = "Create account"; +"screen_create_new_recovery_key_list_item_1" = "Open %1$@ in a desktop device"; +"screen_create_new_recovery_key_list_item_2" = "Sign into your account again"; +"screen_create_new_recovery_key_list_item_3" = "When asked to verify your device, select %1$@"; +"screen_create_new_recovery_key_list_item_3_reset_all" = "โ€œReset allโ€"; +"screen_create_new_recovery_key_list_item_4" = "Follow the instructions to create a new recovery key"; +"screen_create_new_recovery_key_list_item_5" = "Save your new recovery key in a password manager or encrypted note"; +"screen_create_new_recovery_key_title" = "Reset the encryption for your account using another device"; +"screen_create_poll_add_option_btn" = "Variant qo'shish"; +"screen_create_poll_anonymous_desc" = "Natijalarni faqat soสปrov tugagandan keyin koสปrsatish"; +"screen_create_poll_anonymous_headline" = "Ovozlarni yashirish"; +"screen_create_poll_answer_hint" = "Variant%1$d"; +"screen_create_poll_cancel_confirmation_content_ios" = "Oสปzgartirishlaringiz saqlanmaydi"; +"screen_create_poll_cancel_confirmation_title_ios" = "Soโ€˜rovni bekor qilish"; +"screen_create_poll_question_desc" = "Savol yoki mavzu"; +"screen_create_poll_question_hint" = "So'rovnoma nima haqida?"; +"screen_create_poll_title" = "Soโ€˜rovnoma yaratish"; +"screen_create_room_action_create_room" = "Yangi xona"; +"screen_create_room_error_creating_room" = "Xonani yaratishda xatolik yuz berdi"; +"screen_create_room_private_option_description" = "Bu xonadagi xabarlar shifrlangan. Keyinchalik shifrlashni oโ€˜chirib boโ€˜lmaydi."; +"screen_create_room_private_option_title" = "Shaxsiy xona (faqat taklif)"; +"screen_create_room_public_option_description" = "Xabarlar shifrlanmagan va har kim ularni o'qiy oladi. Keyinchalik shifrlashni yoqishingiz mumkin."; +"screen_create_room_public_option_title" = "Jamoat xonasi (har kim)"; +"screen_create_room_topic_label" = "Mavzu (ixtiyoriy)"; +"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_edit_poll_delete_confirmation" = "Are you sure you want to delete this poll?"; +"screen_edit_profile_display_name" = "Ko'rsatiladigan ism"; +"screen_edit_profile_display_name_placeholder" = "Ismingizni ko'rsating"; +"screen_edit_profile_error" = "Noma'lum xatolik yuz berdi va ma'lumotni o'zgartirib bo'lmadi."; +"screen_edit_profile_error_title" = "Profilni yangilab boโ€˜lmadi"; +"screen_edit_profile_title" = "Profilni tahrirlash"; +"screen_edit_profile_updating_details" = "Profil yangilanmoqdaโ€ฆ"; +"screen_encryption_reset_action_continue_reset" = "Continue reset"; +"screen_encryption_reset_bullet_1" = "Your account details, contacts, preferences, and chat list will be kept"; +"screen_encryption_reset_bullet_2" = "You will lose your existing message history"; +"screen_encryption_reset_bullet_3" = "You will need to verify all your existing devices and contacts again"; +"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_identity_confirmation_create_new_recovery_key" = "Create a new recovery key"; +"screen_identity_confirmation_subtitle" = "Verify this device to set up secure messaging."; +"screen_identity_confirmation_title" = "Confirm your identity"; +"screen_identity_confirmation_use_another_device" = "Use another device"; +"screen_identity_confirmation_use_recovery_key" = "Use recovery key"; +"screen_identity_confirmed_subtitle" = "Now you can read or send messages securely, and anyone you chat with can also trust this device."; +"screen_identity_confirmed_title" = "Device verified"; +"screen_identity_waiting_on_other_device" = "Waiting on other deviceโ€ฆ"; +"screen_invites_decline_chat_message" = "Haqiqatan ham qo'shilish taklifini rad qilmoqchimisiz%1$@ ?"; +"screen_invites_decline_chat_title" = "Taklifni rad etish"; +"screen_invites_decline_direct_chat_message" = "Haqiqatan ham bu shaxsiy chatni rad qilmoqchimisiz%1$@ ?"; +"screen_invites_decline_direct_chat_title" = "Chatni rad etish"; +"screen_invites_empty_list" = "Takliflar yo'q"; +"screen_invites_invited_you" = "%1$@(%2$@ ) sizni taklif qildi"; +"screen_join_room_join_action" = "Join room"; +"screen_join_room_knock_action" = "Knock to join"; +"screen_join_room_space_not_supported_description" = "%1$@ does not support spaces yet. You can access spaces on web."; +"screen_join_room_space_not_supported_title" = "Spaces are not supported yet"; +"screen_join_room_subtitle_knock" = "Click the button below and a room administrator will be notified. Youโ€™ll be able to join the conversation once approved."; +"screen_join_room_subtitle_no_preview" = "You must be a member of this room to view the message history."; +"screen_join_room_title_knock" = "Want to join this room?"; +"screen_join_room_title_no_preview" = "Preview is not available"; +"screen_key_backup_disable_confirmation_action_turn_off" = "O'chirish"; +"screen_key_backup_disable_confirmation_description" = "Agar barcha qurilmalardan chiqqan boสปlsangiz, shifrlangan xabarlaringizni yoสปqotasiz."; +"screen_key_backup_disable_confirmation_title" = "Haqiqatan ham zaxiralashni oโ€˜chirib qoโ€˜ymoqchimisiz?"; +"screen_key_backup_disable_description" = "Zaxiralashni oโ€˜chirib qoโ€˜ysangiz, joriy shifrlash kaliti zaxira nusxasi oโ€˜chiriladi va boshqa xavfsizlik funksiyalari oโ€˜chiriladi. Bunday holda siz:"; +"screen_key_backup_disable_description_point_1" = "Yangi qurilmalarda shifrlangan xabarlar tarixi mavjud emas"; +"screen_key_backup_disable_description_point_2" = "Agar tizimdan chiqqan boสปlsangiz, shifrlangan xabarlaringizga kirish huquqini yoสปqotasiz%1$@ hamma joyda"; +"screen_key_backup_disable_title" = "Haqiqatan ham zaxiralashni oโ€˜chirib qoโ€˜ymoqchimisiz?"; +"screen_login_error_deactivated_account" = "Bu hisob oโ€˜chirilgan."; +"screen_login_error_invalid_credentials" = "Notog'ri foydalanuvchi nomi va/yoki parol"; +"screen_login_error_invalid_user_id" = "Bu haqiqiy foydalanuvchi identifikatori emas. Kutilayotgan format: '@user:homeserver.org'"; +"screen_login_error_refresh_tokens" = "This server is configured to use refresh tokens. These aren't supported when using password based login."; +"screen_login_error_unsupported_authentication" = "Tanlangan uy serveri parol yoki OIDC loginni qo'lab-quvvatlamaydi. Iltimos, administratoringizga murojaat qiling yoki boshqa uy serverini tanlang."; +"screen_login_form_header" = "Tafsilotlaringizni kiriting"; +"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."; +"screen_notification_optin_title" = "Bildirishnomalarga ruxsat bering va hech qachon xabarni o'tkazib yubormang"; +"screen_notification_settings_additional_settings_section_title" = "Qo'shimcha sozlamalar"; +"screen_notification_settings_calls_label" = "Audio va video qo'ng'iroqlar"; +"screen_notification_settings_configuration_mismatch" = "Konfiguratsiya mos kelmasligi"; +"screen_notification_settings_configuration_mismatch_description" = "Variantlarni topishni osonlashtirish uchun bildirishnomalar sozlamalarini soddalashtirdik. Ilgari siz tanlagan baสผzi shaxsiy sozlamalar bu yerda koสปrsatilmaydi, lekin ular hali ham faol. \n\nDavom ettirsangiz, baสผzi sozlamalaringiz oสปzgarishi mumkin."; +"screen_notification_settings_direct_chats" = "To'g'ridan-to'g'ri suhbatlar"; +"screen_notification_settings_edit_custom_settings_section_title" = "Har bir suhbat uchun moslashtirilgan sozlama"; +"screen_notification_settings_edit_failed_updating_default_mode" = "Bildirishnoma sozlamalarini yangilashda xatolik yuz berdi."; +"screen_notification_settings_edit_mode_all_messages" = "Barcha xabarlar"; +"screen_notification_settings_edit_mode_mentions_and_keywords" = "Faqat eslatmalar va kalit so'zlar"; +"screen_notification_settings_edit_screen_direct_section_header" = "To'g'ridan-to'g'ri suhbats, menga xabar bering"; +"screen_notification_settings_edit_screen_group_section_header" = "Guruh suhbatlarida menga xabar bering"; +"screen_notification_settings_enable_notifications" = "Ushbu qurilmada bildirishnomalarni yoqing"; +"screen_notification_settings_failed_fixing_configuration" = "Konfiguratsiya tuzatilmadi, qayta urinib ko'ring."; +"screen_notification_settings_group_chats" = "Guruh suhbatlari"; +"screen_notification_settings_invite_for_me_label" = "Invitations"; +"screen_notification_settings_mentions_only_disclaimer" = "Your homeserver does not support this option in encrypted rooms, you may not get notified in some rooms."; +"screen_notification_settings_mentions_section_title" = "Eslatmalar"; +"screen_notification_settings_mode_all" = "Hammasi"; +"screen_notification_settings_mode_mentions" = "Eslatmalar"; +"screen_notification_settings_notification_section_title" = "Menga xabar bering"; +"screen_notification_settings_room_mention_label" = "Menga @room orqali xabar bering"; +"screen_notification_settings_system_notifications_action_required" = "Bildirishnomalarni olish uchun, iltimos, o'zingizni %1$@ingizni o'zgartiring."; +"screen_notification_settings_system_notifications_action_required_content_link" = "tizim sozlamalari"; +"screen_notification_settings_system_notifications_turned_off" = "Tizim bildirishnomalari o'chirilgan"; +"screen_notification_settings_title" = "Bildirishnomalar"; +"screen_onboarding_sign_in_manually" = "Qo'lda tizimga kiring"; +"screen_onboarding_sign_in_with_qr_code" = "QR kod bilan tizimga kiring"; +"screen_onboarding_sign_up" = "Hisob yaratish"; +"screen_onboarding_welcome_message" = "Eng tezkor %1$@ga xush kelibsiz. Tezlik va oddylik uchun super zaryadlangan."; +"screen_onboarding_welcome_subtitle" = "%1$@ga Xush kelibsiz. Tezlik va oddylik uchun o'ta zaryadlangan."; +"screen_onboarding_welcome_title" = "Elementingizda bo'ling"; +"screen_polls_history_empty_ongoing" = "Can't find any ongoing polls."; +"screen_polls_history_empty_past" = "Can't find any past polls."; +"screen_polls_history_filter_ongoing" = "Ongoing"; +"screen_polls_history_filter_past" = "Past"; +"screen_polls_history_title" = "Polls"; +"screen_qr_code_login_connecting_subtitle" = "Establishing a secure connection"; +"screen_qr_code_login_connection_note_secure_state_description" = "A secure connection could not be made to the new device. Your existing devices are still safe and you don't need to worry about them."; +"screen_qr_code_login_connection_note_secure_state_list_header" = "What now?"; +"screen_qr_code_login_connection_note_secure_state_list_item_1" = "Try signing in again with a QR code in case this was a network problem"; +"screen_qr_code_login_connection_note_secure_state_list_item_2" = "If you encounter the same problem, try a different wifi network or use your mobile data instead of wifi"; +"screen_qr_code_login_connection_note_secure_state_list_item_3" = "If that doesnโ€™t work, sign in manually"; +"screen_qr_code_login_connection_note_secure_state_title" = "Connection not secure"; +"screen_qr_code_login_device_code_subtitle" = "Youโ€™ll be asked to enter the two digits shown on this device."; +"screen_qr_code_login_device_code_title" = "Enter the number below on your other device"; +"screen_qr_code_login_device_not_signed_in_scan_state_description" = "Sign in to your other device and then try again, or use another device thatโ€™s already signed in."; +"screen_qr_code_login_device_not_signed_in_scan_state_subtitle" = "Other device not signed in"; +"screen_qr_code_login_error_cancelled_subtitle" = "The sign in was cancelled on the other device."; +"screen_qr_code_login_error_cancelled_title" = "Sign in request cancelled"; +"screen_qr_code_login_error_declined_subtitle" = "The sign in was declined on the other device."; +"screen_qr_code_login_error_declined_title" = "Sign in declined"; +"screen_qr_code_login_error_expired_subtitle" = "Sign in expired. Please try again."; +"screen_qr_code_login_error_expired_title" = "The sign in was not completed in time"; +"screen_qr_code_login_error_linking_not_suported_subtitle" = "Your other device does not support signing in to %@ with a QR code.\n\nTry signing in manually, or scan the QR code with another device."; +"screen_qr_code_login_error_linking_not_suported_title" = "QR code not supported"; +"screen_qr_code_login_error_sliding_sync_not_supported_subtitle" = "Your account provider does not support %1$@."; +"screen_qr_code_login_error_sliding_sync_not_supported_title" = "%1$@ not supported"; +"screen_qr_code_login_initial_state_button_title" = "Ready to scan"; +"screen_qr_code_login_initial_state_item_1" = "Open %1$@ on a desktop device"; +"screen_qr_code_login_initial_state_item_2" = "Click on your avatar"; +"screen_qr_code_login_initial_state_item_3" = "Select %1$@"; +"screen_qr_code_login_initial_state_item_3_action" = "โ€œLink new deviceโ€"; +"screen_qr_code_login_initial_state_item_4" = "Scan the QR code with this device"; +"screen_qr_code_login_initial_state_title" = "Open %1$@ on another device to get the QR code"; +"screen_qr_code_login_invalid_scan_state_description" = "Use the QR code shown on the other device."; +"screen_qr_code_login_invalid_scan_state_subtitle" = "Wrong QR code"; +"screen_qr_code_login_no_camera_permission_button" = "Go to camera settings"; +"screen_qr_code_login_no_camera_permission_state_description" = "You need to give permission for %1$@ to use your deviceโ€™s camera in order to continue."; +"screen_qr_code_login_no_camera_permission_state_title" = "Allow camera access to scan the QR code"; +"screen_qr_code_login_scanning_state_title" = "Scan the QR code"; +"screen_qr_code_login_start_over_button" = "Start over"; +"screen_qr_code_login_unknown_error_description" = "An unexpected error occurred. Please try again."; +"screen_qr_code_login_verify_code_loading" = "Waiting for your other device"; +"screen_qr_code_login_verify_code_subtitle" = "Your account provider may ask for the following code to verify the sign in."; +"screen_qr_code_login_verify_code_title" = "Your verification code"; +"screen_recovery_key_change_description" = "Mavjud kalitingizni yo'qotgan bo'lsangiz, yangi tiklash kalitini oling. Qayta tiklash kalitini almashtirganingizdan so'ng, eski kalitingiz ishlamaydi."; +"screen_recovery_key_change_generate_key" = "Yangi tiklash kalitini yarating"; +"screen_recovery_key_change_generate_key_description" = "Qayta tiklash kalitingizni xavfsiz joyda saqlashingiz mumkinligiga ishonch hosil qiling"; +"screen_recovery_key_change_success" = "Qayta tiklash kaliti oสปzgartirildi"; +"screen_recovery_key_change_title" = "Qayta tiklash kaliti almashtirilsinmi?"; +"screen_recovery_key_confirm_create_new_recovery_key" = "Create new recovery key"; +"screen_recovery_key_confirm_description" = "Hech kim bu ekranni kora olmasligiga ishonch hosil qiling!"; +"screen_recovery_key_confirm_error_content" = "Please try again to confirm access to your chat backup."; +"screen_recovery_key_confirm_error_title" = "Incorrect recovery key"; +"screen_recovery_key_confirm_key_description" = "Agar sizda xavfsizlik kaliti yoki xavfsizlik iborasi bolsa, bu ham ishlaydi."; +"screen_recovery_key_confirm_key_placeholder" = "Kirishโ€ฆ"; +"screen_recovery_key_confirm_lost_recovery_key" = "Lost your recovery key?"; +"screen_recovery_key_confirm_success" = "Qayta tiklash kaliti tasdiqlandi"; +"screen_recovery_key_confirm_title" = "Qayta tiklash kalitingizni kiriting"; +"screen_recovery_key_copied_to_clipboard" = "Copied recovery key"; +"screen_recovery_key_generating_key" = "Generatingโ€ฆ"; +"screen_recovery_key_save_action" = "Qayta tiklash kalitini saqlang"; +"screen_recovery_key_save_description" = "Qayta tiklash kalitingizni xavfsiz joyga yozing yoki parol menejerida saqlang."; +"screen_recovery_key_save_key_description" = "Qayta tiklash kalitidan nusxa olish uchun bosing"; +"screen_recovery_key_save_title" = "Zaxira kalitingizni saqlang"; +"screen_recovery_key_setup_confirmation_description" = "Ushbu qadamdan soโ€˜ng siz yangi tiklash kalitingizga kira olmaysiz."; +"screen_recovery_key_setup_confirmation_title" = "Zaxira kalitingizni saqladingizmi?"; +"screen_recovery_key_setup_description" = "Suhbatingiz zaxira nusxasi tiklash kaliti bilan himoyalangan. Agar sozlashdan keyin sizga yangi tiklash kaliti kerak boสปlsa, โ€œQayta tiklash kalitini oสปzgartirishโ€ni tanlash orqali qayta yaratishingiz mumkin."; +"screen_recovery_key_setup_generate_key" = "Qayta tiklash kalitini yarating"; +"screen_recovery_key_setup_generate_key_description" = "Qayta tiklash kalitingizni xavfsiz joyda saqlashingiz mumkinligiga ishonch hosil qiling"; +"screen_recovery_key_setup_success" = "Qayta tiklash muvaffaqiyatli sozlandi"; +"screen_recovery_key_setup_title" = "Qayta tiklashni sozlang"; +"screen_report_content_block_user_hint" = "Ushbu foydalanuvchidan barcha joriy va kelajakdagi xabarlarni yashirishni xohlayotganingizni tekshiring"; +"screen_report_content_explanation" = "Bu xabar uy serveringiz administratoriga xabar qilinadi. Ular hech qanday shifrlangan xabarlarni o'qiy olmaydi."; +"screen_report_content_hint" = "Ushbu kontent haqida xabar berish sababi"; +"screen_reset_encryption_confirmation_alert_action" = "Yes, reset now"; +"screen_reset_encryption_confirmation_alert_subtitle" = "This process is irreversible."; +"screen_reset_encryption_confirmation_alert_title" = "Are you sure you want to reset your identity?"; +"screen_reset_encryption_password_placeholder" = "Enterโ€ฆ"; +"screen_reset_encryption_password_subtitle" = "Confirm that you want to reset your identity."; +"screen_reset_encryption_password_title" = "Enter your account password to continue"; +"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_room_alias_resolver_resolve_alias_failure" = "Failed to resolve room alias."; +"screen_room_attachment_source_camera" = "Kamera"; +"screen_room_attachment_source_camera_video" = "Video yozib olish"; +"screen_room_attachment_source_files" = "Biriktirma"; +"screen_room_attachment_source_gallery" = "Fotosurat va video kutubxonasi"; +"screen_room_attachment_source_location" = "Joylashuv"; +"screen_room_attachment_source_poll" = "So'ro'vnoma"; +"screen_room_attachment_text_formatting" = "Matnni formatlash"; +"screen_room_change_permissions_administrators" = "Admins only"; +"screen_room_change_permissions_ban_people" = "Ban people"; +"screen_room_change_permissions_delete_messages" = "Remove messages"; +"screen_room_change_permissions_invite_people" = "Invite people"; +"screen_room_change_permissions_moderators" = "Admins and moderators"; +"screen_room_change_permissions_remove_people" = "Remove people"; +"screen_room_change_permissions_room_avatar" = "Change room avatar"; +"screen_room_change_permissions_room_name" = "Change room name"; +"screen_room_change_permissions_room_topic" = "Change room topic"; +"screen_room_change_permissions_send_messages" = "Send messages"; +"screen_room_change_role_administrators_title" = "Edit Admins"; +"screen_room_change_role_confirm_add_admin_description" = "You will not be able to undo this action. You are promoting the user to have the same power level as you."; +"screen_room_change_role_confirm_add_admin_title" = "Add Admin?"; +"screen_room_change_role_confirm_demote_self_action" = "Demote"; +"screen_room_change_role_confirm_demote_self_description" = "You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the room it will be impossible to regain privileges."; +"screen_room_change_role_confirm_demote_self_title" = "Demote yourself?"; +"screen_room_change_role_invited_member_name" = "%1$@ (Pending)"; +"screen_room_change_role_moderators_admin_section_footer" = "Admins automatically have moderator privileges"; +"screen_room_change_role_moderators_title" = "Edit Moderators"; +"screen_room_change_role_unsaved_changes_description" = "You have unsaved changes."; +"screen_room_change_role_unsaved_changes_title" = "Save changes?"; +"screen_room_details_add_topic_title" = "Mavzu qo'shish"; +"screen_room_details_already_a_member" = "Allaqachon a'zo"; +"screen_room_details_already_invited" = "Allaqachon taklif qilingan"; +"screen_room_details_badge_encrypted" = "Encrypted"; +"screen_room_details_badge_not_encrypted" = "Not encrypted"; +"screen_room_details_badge_public" = "Public room"; +"screen_room_details_edit_room_title" = "Xonani tahrirlash"; +"screen_room_details_edition_error" = "Nomaสผlum xatolik yuz berdi va maสผlumotni oสปzgartirib boสปlmadi."; +"screen_room_details_edition_error_title" = "Xonani yangilab boโ€˜lmadi"; +"screen_room_details_encryption_enabled_subtitle" = "Xabarlar qulflar bilan himoyalangan. Faqat siz va qabul qiluvchilar ularni qulfdan chiqarish uchun noyob kalitlarga ega."; +"screen_room_details_encryption_enabled_title" = "Xabarni shifrlash yoqilgan"; +"screen_room_details_error_loading_notification_settings" = "Bildirishnoma sozlamalarini yuklashda xatolik yuz berdi."; +"screen_room_details_error_muting" = "Bu xona ovozini oโ€˜chirib boโ€˜lmadi, qayta urinib koโ€˜ring."; +"screen_room_details_error_unmuting" = "Bu xonaning ovozi yoqilmadi, qayta urinib koโ€˜ring."; +"screen_room_details_notification_mode_custom" = "Maxsus"; +"screen_room_details_notification_mode_default" = "Standart"; +"screen_room_details_notification_title" = "Bildirishnomalar"; +"screen_room_details_share_room_title" = "Xonani baham ko'ring"; +"screen_room_details_title" = "Room info"; +"screen_room_details_updating_room" = "Xona yangilanmoqdaโ€ฆ"; +"screen_room_directory_search_loading_error" = "Failed loading"; +"screen_room_directory_search_title" = "Room directory"; +"screen_room_encrypted_history_banner" = "Xabarlar tarixi hozirda mavjud emas."; +"screen_room_encrypted_history_banner_unverified" = "Message history is unavailable in this room. Verify this device to see your message history."; +"screen_room_error_failed_retrieving_user_details" = "Foydalanuvchi tafsilotlarini olinmadi"; +"screen_room_invite_again_alert_message" = "Ularni yana taklif qilmoqchimisiz?"; +"screen_room_invite_again_alert_title" = "Siz bu chatda yolg'izsiz"; +"screen_room_member_details_block_alert_action" = "Bloklash"; +"screen_room_member_details_block_alert_description" = "Bloklangan foydalanuvchilar sizga xabar yubora olmaydi va ularning barcha xabarlari yashiriladi. Ularni istalgan vaqtda blokdan chiqarishingiz mumkin."; +"screen_room_member_details_block_user" = "Foydalanuvchini bloklash"; +"screen_room_member_details_title" = "Profile"; +"screen_room_member_details_unblock_alert_action" = "Blokdan chiqarish"; +"screen_room_member_details_unblock_alert_description" = "Ulardan kelgan barcha xabarlarni yana koสปrishingiz mumkin boสปladi."; +"screen_room_member_details_unblock_user" = "Foydalanuvchini blokdan chiqarish"; +"screen_room_member_list_ban_member_confirmation_action" = "Ban"; +"screen_room_member_list_ban_member_confirmation_description" = "They wonโ€™t be able to join this room again if invited."; +"screen_room_member_list_ban_member_confirmation_title" = "Are you sure you want to ban this member?"; +"screen_room_member_list_banned_empty" = "There are no banned users in this room."; +"screen_room_member_list_banning_user" = "Banning %1$@"; +"screen_room_member_list_manage_member_ban" = "Remove and ban member"; +"screen_room_member_list_manage_member_remove" = "Remove from room"; +"screen_room_member_list_manage_member_remove_confirmation_ban" = "Remove and ban member"; +"screen_room_member_list_manage_member_remove_confirmation_kick" = "Only remove member"; +"screen_room_member_list_manage_member_remove_confirmation_title" = "Remove member and ban from joining in the future?"; +"screen_room_member_list_manage_member_unban_action" = "Unban"; +"screen_room_member_list_manage_member_unban_message" = "They will be able to join this room again if invited."; +"screen_room_member_list_manage_member_unban_title" = "Unban user"; +"screen_room_member_list_manage_member_user_info" = "View profile"; +"screen_room_member_list_mode_banned" = "Banned"; +"screen_room_member_list_mode_members" = "Members"; +"screen_room_member_list_pending_header_title" = "Kutilmoqda"; +"screen_room_member_list_removing_user" = "Removing %1$@โ€ฆ"; +"screen_room_member_list_role_administrator" = "Admin"; +"screen_room_member_list_role_moderator" = "Moderator"; +"screen_room_member_list_room_members_header_title" = "Xona a'zolari"; +"screen_room_member_list_unbanning_user" = "Unbanning %1$@"; +"screen_room_notification_settings_allow_custom" = "Moslashtirilgan sozlamalarga ruxsat bering"; +"screen_room_notification_settings_allow_custom_footnote" = "Buni yoqsangiz, standart sozlamalaringiz bekor qilinadi"; +"screen_room_notification_settings_custom_settings_title" = "Bu chatda menga xabar bering"; +"screen_room_notification_settings_default_setting_footnote" = "Siz buni o'zgartira olasiz o'zingizning %1$@da."; +"screen_room_notification_settings_default_setting_footnote_content_link" = "global sozlamalar"; +"screen_room_notification_settings_default_setting_title" = "Standart sozlama"; +"screen_room_notification_settings_edit_remove_setting" = "Maxsus sozlamani olib tashlang"; +"screen_room_notification_settings_error_loading_settings" = "Bildirishnoma sozlamalarini yuklashda xatolik yuz berdi."; +"screen_room_notification_settings_error_restoring_default" = "Standart rejimni tiklab boโ€˜lmadi, qaytadan urinib koโ€˜ring."; +"screen_room_notification_settings_error_setting_mode" = "Rejimni oโ€˜rnatib boโ€˜lmadi, qayta urinib koโ€˜ring."; +"screen_room_notification_settings_mentions_only_disclaimer" = "Your homeserver does not support this option in encrypted rooms, you won't get notified in this room."; +"screen_room_notification_settings_mode_all_messages" = "Barcha xabarlar"; +"screen_room_notification_settings_room_custom_settings_title" = "Bu xonada menga xabar bering"; +"screen_room_retry_send_menu_send_again_action" = "Yana yuboring"; +"screen_room_retry_send_menu_title" = "Xabaringiz yuborilmadi"; +"screen_room_roles_and_permissions_admins" = "Admins"; +"screen_room_roles_and_permissions_change_my_role" = "Change my role"; +"screen_room_roles_and_permissions_change_role_demote_to_member" = "Demote to member"; +"screen_room_roles_and_permissions_change_role_demote_to_moderator" = "Demote to moderator"; +"screen_room_roles_and_permissions_member_moderation" = "Member moderation"; +"screen_room_roles_and_permissions_messages_and_content" = "Messages and content"; +"screen_room_roles_and_permissions_moderators" = "Moderators"; +"screen_room_roles_and_permissions_permissions_header" = "Permissions"; +"screen_room_roles_and_permissions_reset" = "Reset permissions"; +"screen_room_roles_and_permissions_reset_confirm_description" = "Once you reset permissions, you will lose the current settings."; +"screen_room_roles_and_permissions_reset_confirm_title" = "Reset permissions?"; +"screen_room_roles_and_permissions_roles_header" = "Roles"; +"screen_room_roles_and_permissions_room_details" = "Room details"; +"screen_room_roles_and_permissions_title" = "Roles and permissions"; +"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_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"; +"screen_room_timeline_reactions_show_less" = "Kamroq ko'rsatish"; +"screen_room_timeline_reactions_show_more" = "Ko'proq ko'rsatish"; +"screen_room_timeline_read_marker_title" = "Yangi"; +"screen_room_title" = "Chat"; +"screen_room_typing_many_members_first_component_ios" = "%1$@, %2$@ and "; +"screen_room_typing_notification_plural_ios" = " are typingโ€ฆ"; +"screen_room_typing_notification_singular_ios" = " is typingโ€ฆ"; +"screen_room_typing_two_members" = "%1$@ and %2$@"; +"screen_room_voice_message_tooltip" = "Yozib olish uchun bosib turing"; +"screen_roomlist_a11y_create_message" = "Yangi suhbat yoki xona yarating"; +"screen_roomlist_empty_message" = "Kimgadir xabar yuborishdan boshlang."; +"screen_roomlist_empty_title" = "Hozircha chatlar yoโ€˜q."; +"screen_roomlist_filter_favourites" = "Favourites"; +"screen_roomlist_filter_favourites_empty_state_subtitle" = "You can add a chat to your favourites in the chat settings.\nFor now, you can deselect filters in order to see your other chats"; +"screen_roomlist_filter_favourites_empty_state_title" = "You donโ€™t have favourite chats yet"; +"screen_roomlist_filter_invites" = "Invites"; +"screen_roomlist_filter_invites_empty_state_title" = "You don't have any pending invites."; +"screen_roomlist_filter_low_priority" = "Low Priority"; +"screen_roomlist_filter_mixed_empty_state_subtitle" = "You can deselect filters in order to see your other chats"; +"screen_roomlist_filter_mixed_empty_state_title" = "You donโ€™t have chats for this selection"; +"screen_roomlist_filter_people_empty_state_title" = "You donโ€™t have any DMs yet"; +"screen_roomlist_filter_rooms" = "Rooms"; +"screen_roomlist_filter_rooms_empty_state_title" = "Youโ€™re not in any room yet"; +"screen_roomlist_filter_unreads" = "Unreads"; +"screen_roomlist_filter_unreads_empty_state_title" = "Congrats!\nYou donโ€™t have any unread messages!"; +"screen_roomlist_main_space_title" = "Suhbatlar"; +"screen_roomlist_mark_as_read" = "Mark as read"; +"screen_roomlist_mark_as_unread" = "Mark as unread"; +"screen_roomlist_room_directory_button_title" = "Browse all rooms"; +"screen_server_confirmation_change_server" = "Hisob provayderini o'zgartiring"; +"screen_server_confirmation_message_login_element_dot_io" = "Element xodimlari uchun shaxsiy server."; +"screen_server_confirmation_message_login_matrix_dot_org" = "Matrix xavfsiz, markazlashmagan aloqa uchun ochiq tarmoqdir."; +"screen_server_confirmation_message_register" = "Bu sizning suhbatlaringiz yashaydigan joy - xuddi siz elektron pochta xabarlaringizni saqlash uchun elektron pochta provayderidan foydalanganingiz kabi."; +"screen_server_confirmation_title_login" = "Siz tizimga kirmoqchisiz%1$@"; +"screen_server_confirmation_title_register" = "Hisob yaratmoqchisiz%1$@"; +"screen_session_verification_cancelled_subtitle" = "Nimadir notoโ€˜gโ€˜ri koโ€˜rinadi. Yoki soโ€˜rov muddati tugadi yoki soโ€˜rov rad etildi."; +"screen_session_verification_compare_emojis_subtitle" = "Quyidagi kulgichlar boshqa seansda koโ€˜rsatilganlarga mos kelishini tasdiqlang."; +"screen_session_verification_compare_emojis_title" = "Emojilarni solishtiring"; +"screen_session_verification_compare_numbers_subtitle" = "Confirm that the numbers below match those shown on your other session."; +"screen_session_verification_compare_numbers_title" = "Compare numbers"; +"screen_session_verification_complete_subtitle" = "Yangi seansingiz tasdiqlandi. U sizning shifrlangan xabarlaringizga kirish huquqiga ega va boshqa foydalanuvchilar uni ishonchli deb bilishadi."; +"screen_session_verification_enter_recovery_key" = "Enter recovery key"; +"screen_session_verification_open_existing_session_subtitle" = "Shifrlangan xabarlar tarixiga kirish uchun shaxsingizni tasdiqlang."; +"screen_session_verification_open_existing_session_title" = "Mavjud seansni oching"; +"screen_session_verification_positive_button_canceled" = "Tasdiqlashni qaytadan urining"; +"screen_session_verification_positive_button_initial" = "Men tayyorman"; +"screen_session_verification_positive_button_verifying_ongoing" = "Mos kelishi kutilmoqda"; +"screen_session_verification_ready_subtitle" = "Compare a unique set of emojis."; +"screen_session_verification_request_accepted_subtitle" = "Noyob emojilarni solishtiring, ular bir xil tartibda paydo bo'lishiga ishonch hosil qiling."; +"screen_session_verification_they_dont_match" = "Ular mos kelmaydi"; +"screen_session_verification_they_match" = "Ular mos keladi"; +"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"; +"screen_share_my_location_action" = "Joylashuvimni ulashing"; +"screen_share_open_apple_maps" = "Apple Mapsda oching"; +"screen_share_open_google_maps" = "Google Mapsda oching"; +"screen_share_open_osm_maps" = "OpenStreetMapda oching"; +"screen_share_this_location_action" = "Bu joylashuvni ulashing"; +"screen_signed_out_reason_1" = "Siz boshqa seansda parolingizni o'zgartirdingiz"; +"screen_signed_out_reason_2" = "Siz seansni boshqa seansdan o'chirib tashladingiz"; +"screen_signed_out_reason_3" = "Serveringiz administratori ruxsatingizni bekor qildi"; +"screen_signed_out_subtitle" = "Siz quyida sanab oโ€˜tilgan sabablardan biri tufayli tizimdan chiqqan boโ€˜lishingiz mumkin. Foydalanishni davom ettirish uchun qayta kiring%@ ."; +"screen_signed_out_title" = "Hisobingizdan chiqdingiz"; +"screen_signout_confirmation_dialog_content" = "Haqiqatan ham tizimdan chiqmoqchimisiz?"; +"screen_signout_in_progress_dialog_content" = "Chiqishโ€ฆ"; +"screen_signout_key_backup_disabled_subtitle" = "You are about to sign out of your last session. If you sign out now, you will lose access to your encrypted messages."; +"screen_signout_key_backup_disabled_title" = "You have turned off backup"; +"screen_signout_key_backup_offline_subtitle" = "Your keys were still being backed up when you went offline. Reconnect so that your keys can be backed up before signing out."; +"screen_signout_key_backup_offline_title" = "Your keys are still being backed up"; +"screen_signout_key_backup_ongoing_subtitle" = "Please wait for this to complete before signing out."; +"screen_signout_key_backup_ongoing_title" = "Your keys are still being backed up"; +"screen_signout_recovery_disabled_subtitle" = "You are about to sign out of your last session. If you sign out now, you'll lose access to your encrypted messages."; +"screen_signout_recovery_disabled_title" = "Recovery not set up"; +"screen_signout_save_recovery_key_subtitle" = "You are about to sign out of your last session. If you sign out now, you might lose access to your encrypted messages."; +"screen_signout_save_recovery_key_title" = "Have you saved your recovery key?"; +"screen_start_chat_error_starting_chat" = "Suhbatni boshlashda xatolik yuz berdi"; +"screen_view_location_title" = "Joylashuv"; +"screen_welcome_bullet_1" = "Qo'ng'iroqlar, so'ro'vlar, qidiruv va boshqalar shu yil oxirida qo'shiladi."; +"screen_welcome_bullet_2" = "Shifrlangan xonalar uchun xabarlar tarixi hali mavjud emas."; +"screen_welcome_bullet_3" = "Biz sizdan eshitishni istardik, sozlamalar sahifasi orqali fikringizni bildiring."; +"screen_welcome_button" = "Qani ketdik!"; +"screen_welcome_subtitle" = "Buni bilishingiz kerak:"; +"screen_welcome_title" = "%1$@ga Xush kelibsiz!"; +"session_verification_banner_message" = "Siz yangi qurilmadan foydalanayotganga oโ€˜xshaysiz. Shifrlangan xabarlaringizga kirish uchun boshqa qurilma bilan tasdiqlang."; +"session_verification_banner_title" = "Siz ekanligingizni tasdiqlang"; +"settings_rageshake" = "G'azablanish"; +"settings_rageshake_detection_threshold" = "Aniqlash chegarasi"; +"settings_version_number" = "Versiya:%1$@ (%2$@ )"; +"state_event_avatar_changed_too" = "(avatar ham o'zgartirildi)"; +"state_event_avatar_url_changed" = "%1$@ avatarini o'zgartirdi"; +"state_event_avatar_url_changed_by_you" = "Siz avataringizni o'zgartirdingiz"; +"state_event_demoted_to_member" = "%1$@ was demoted to member"; +"state_event_demoted_to_moderator" = "%1$@ was demoted to moderator"; +"state_event_display_name_changed_from" = "%1$@ ko'rsatiladigan nomini %2$@dan %3$@ga o'zgartirdi"; +"state_event_display_name_changed_from_by_you" = "Siz ko'rsatiladigan nomingizni %1$@ dan %2$@ ga o'zgartirdingiz"; +"state_event_display_name_removed" = "%1$@ ko'rinadigan nomini o'chirib tashladi (avval %2$@ bo'lgan edi)"; +"state_event_display_name_removed_by_you" = "Siz ko'rinadigan nomingizni o'chirib tashladingiz (avval %1$@ bo'lgan edi)"; +"state_event_display_name_set" = "%1$@ ularning ko'rsatiladigan nomini o'rnating %2$@"; +"state_event_display_name_set_by_you" = "Siz ko'rsatiladigan nomingizni o'rnating %1$@"; +"state_event_promoted_to_administrator" = "%1$@ was promoted to admin"; +"state_event_promoted_to_moderator" = "%1$@ was promoted to moderator"; +"state_event_room_avatar_changed" = "%1$@ xonani avatarini o'zgartirdi"; +"state_event_room_avatar_changed_by_you" = "Siz xonani avatarini o'zgartirdingiz"; +"state_event_room_avatar_removed" = "%1$@ xonani avatarini o'chirib tashladi"; +"state_event_room_avatar_removed_by_you" = "Siz xonani avatarini o'chirib tashladingiz"; +"state_event_room_ban" = "%1$@taqiqlangan%2$@"; +"state_event_room_ban_by_you" = "Siz taqiqlangansiz%1$@"; +"state_event_room_created" = "%1$@xonani yaratdi"; +"state_event_room_created_by_you" = "Siz xonani yaratdingiz"; +"state_event_room_invite" = "%1$@taklif qilingan%2$@"; +"state_event_room_invite_accepted" = "%1$@taklifni qabul qildi"; +"state_event_room_invite_accepted_by_you" = "Siz taklifni qabul qildingiz"; +"state_event_room_invite_by_you" = "Siz taklif qildingiz%1$@"; +"state_event_room_invite_you" = "%1$@sizni taklif qildi"; +"state_event_room_join" = "%1$@xonaga qo'shildi"; +"state_event_room_join_by_you" = "Siz xonaga qo'shildingiz"; +"state_event_room_knock" = "%1$@ qo'shilishni so'radi"; +"state_event_room_knock_accepted" = "%1$@ %2$@ga qo'shilishga ruxsat berdi"; +"state_event_room_knock_accepted_by_you" = "Siz %1$@ga qo'shilishaga ruxsat berdingiz"; +"state_event_room_knock_by_you" = "Siz qoสปshilishni soสปragansiz"; +"state_event_room_knock_denied" = "%1$@ %2$@ning qo'shilish haqidagi iltimosini rad etdi"; +"state_event_room_knock_denied_by_you" = "Siz %1$@ning qo'shiliz iltimosini rad etdingiz"; +"state_event_room_knock_denied_you" = "%1$@ sizni qo'shilish iltimosingizni rad etdi"; +"state_event_room_knock_retracted" = "%1$@ endi qo'shilishdan manfaatdor emas"; +"state_event_room_knock_retracted_by_you" = "Siz qoสปshilish soสปrovingizni bekor qildingiz"; +"state_event_room_leave" = "%1$@xonani tark etdi"; +"state_event_room_leave_by_you" = "Siz xonani tark etdingiz"; +"state_event_room_name_changed" = "%1$@ xonani nomini %2$@ o'zgartirdi"; +"state_event_room_name_changed_by_you" = "Siz xonani nomini %1$@ ga o'zgartirdingiz"; +"state_event_room_name_removed" = "%1$@ xonani nomini o'chirib tashladi"; +"state_event_room_name_removed_by_you" = "Siz xonani nomini o'chirib tashladingiz"; +"state_event_room_none" = "%1$@ made no changes"; +"state_event_room_none_by_you" = "You made no changes"; +"state_event_room_pinned_events_changed" = "%1$@ changed the pinned messages"; +"state_event_room_pinned_events_changed_by_you" = "You changed the pinned messages"; +"state_event_room_pinned_events_pinned" = "%1$@ pinned a message"; +"state_event_room_pinned_events_pinned_by_you" = "You pinned a message"; +"state_event_room_pinned_events_unpinned" = "%1$@ unpinned a message"; +"state_event_room_pinned_events_unpinned_by_you" = "You unpinned a message"; +"state_event_room_reject" = "%1$@taklifni rad etdi"; +"state_event_room_reject_by_you" = "Siz taklifni rad etdingiz"; +"state_event_room_remove" = "%1$@ o'chirildi %2$@"; +"state_event_room_remove_by_you" = "Siz o'chirildingiz %1$@"; +"state_event_room_third_party_invite" = "%1$@ taklifnoma yubordi %2$@ga xonaga qo'shilish uchun"; +"state_event_room_third_party_invite_by_you" = "Siz taklifnoma yubordingiz %1$@ ga xonaga qo'shilishi uchun"; +"state_event_room_third_party_revoked_invite" = "%1$@ taklifni %2$@ ga xonaga qo'shilish uchun bekor qildi"; +"state_event_room_third_party_revoked_invite_by_you" = "Siz xonaga qo'shilish taklifini %1$@ ga bekor qildingiz"; +"state_event_room_topic_changed" = "%1$@ mavzuni %2$@ o'zgartirdi"; +"state_event_room_topic_changed_by_you" = "Siz mavzuni %1$@ ga o'zgartirdingiz"; +"state_event_room_topic_removed" = "%1$@ xonani mavzusini o'chirib tashladi"; +"state_event_room_topic_removed_by_you" = "Siz xonani mavzusini o'chirib tashladingiz"; +"state_event_room_unban" = "%1$@taqiqlanmagan%2$@"; +"state_event_room_unban_by_you" = "Siz %1$@ taqiqini bekor qildingiz"; +"state_event_room_unknown_membership_change" = "%1$@ aสผzoligiga nomaสผlum oสปzgarishlar kiritdi"; +"test_language_identifier" = "en"; +"test_untranslated_default_language_identifier" = "en"; +"troubleshoot_notifications_entry_point_section" = "Troubleshoot"; +"troubleshoot_notifications_entry_point_title" = "Troubleshoot notifications"; +"troubleshoot_notifications_screen_action" = "Run tests"; +"troubleshoot_notifications_screen_action_again" = "Run tests again"; +"troubleshoot_notifications_screen_failure" = "Some tests failed. Please check the details."; +"troubleshoot_notifications_screen_notice" = "Run the tests to detect any issue in your configuration that may make notifications not behave as expected."; +"troubleshoot_notifications_screen_quick_fix_action" = "Attempt to fix"; +"troubleshoot_notifications_screen_success" = "All tests passed successfully."; +"troubleshoot_notifications_screen_title" = "Troubleshoot notifications"; +"troubleshoot_notifications_screen_waiting" = "Some tests require your attention. Please check the details."; +"troubleshoot_notifications_test_check_permission_description" = "Check that the application can show notifications."; +"troubleshoot_notifications_test_check_permission_title" = "Check permissions"; +"troubleshoot_notifications_test_current_push_provider_description" = "Get the name of the current provider."; +"troubleshoot_notifications_test_current_push_provider_failure" = "No push providers selected."; +"troubleshoot_notifications_test_current_push_provider_success" = "Current push provider: %1$@."; +"troubleshoot_notifications_test_current_push_provider_title" = "Current push provider"; +"troubleshoot_notifications_test_detect_push_provider_description" = "Ensure that the application has at least one push provider."; +"troubleshoot_notifications_test_detect_push_provider_failure" = "No push providers found."; +"troubleshoot_notifications_test_detect_push_provider_title" = "Detect push providers"; +"troubleshoot_notifications_test_display_notification_description" = "Check that the application can display notification."; +"troubleshoot_notifications_test_display_notification_failure" = "The notification has not been clicked."; +"troubleshoot_notifications_test_display_notification_permission_failure" = "Cannot display the notification."; +"troubleshoot_notifications_test_display_notification_success" = "The notification has been clicked!"; +"troubleshoot_notifications_test_display_notification_title" = "Display notification"; +"troubleshoot_notifications_test_display_notification_waiting" = "Please click on the notification to continue the test."; +"troubleshoot_notifications_test_firebase_availability_description" = "Ensure that Firebase is available."; +"troubleshoot_notifications_test_firebase_availability_failure" = "Firebase is not available."; +"troubleshoot_notifications_test_firebase_availability_success" = "Firebase is available."; +"troubleshoot_notifications_test_firebase_availability_title" = "Check Firebase"; +"troubleshoot_notifications_test_firebase_token_description" = "Ensure that Firebase token is available."; +"troubleshoot_notifications_test_firebase_token_failure" = "Firebase token is not known."; +"troubleshoot_notifications_test_firebase_token_success" = "Firebase token: %1$@."; +"troubleshoot_notifications_test_firebase_token_title" = "Check Firebase token"; +"troubleshoot_notifications_test_push_loop_back_description" = "Ensure that the application is receiving push."; +"troubleshoot_notifications_test_push_loop_back_failure_1" = "Error: pusher has rejected the request."; +"troubleshoot_notifications_test_push_loop_back_failure_2" = "Error: %1$@."; +"troubleshoot_notifications_test_push_loop_back_failure_3" = "Error, cannot test 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_title" = "Test Push loop back"; +"troubleshoot_notifications_test_unified_push_description" = "Ensure that UnifiedPush distributors are available."; +"troubleshoot_notifications_test_unified_push_failure" = "No push distributors found."; +"troubleshoot_notifications_test_unified_push_title" = "Check UnifiedPush"; +"dialog_title_error" = "Xato"; +"dialog_title_success" = "Muvaffaqiyat"; +"notification_fallback_content" = "Bildirishnoma"; +"notification_invitation_action_join" = "Qo'shilish"; +"notification_room_action_mark_as_read" = "Mark as read"; +"notification_room_action_quick_reply" = "Tez javob"; +"screen_room_mentions_at_room_title" = "Har kim"; +"screen_account_provider_signin_subtitle" = "Bu sizning suhbatlaringiz yashaydigan joy - xuddi siz elektron pochta xabarlaringizni saqlash uchun elektron pochta provayderidan foydalanganingiz kabi."; +"screen_account_provider_signup_subtitle" = "Bu sizning suhbatlaringiz yashaydigan joy - xuddi siz elektron pochta xabarlaringizni saqlash uchun elektron pochta provayderidan foydalanganingiz kabi."; +"screen_analytics_settings_help_us_improve" = "Muammolarni aniqlashda yordam berish uchun anonim foydalanish maสผlumotlarini baham koสปring."; +"screen_analytics_settings_read_terms" = "Siz bizning barcha shartlarimizni o'qishingiz mumkin%1$@."; +"screen_analytics_settings_read_terms_content_link" = "Bu yerga"; +"screen_blocked_users_unblock_alert_action" = "Blokdan chiqarish"; +"screen_blocked_users_unblock_alert_description" = "Ulardan kelgan barcha xabarlarni yana koสปrishingiz mumkin boสปladi."; +"screen_blocked_users_unblock_alert_title" = "Foydalanuvchini blokdan chiqarish"; +"screen_bug_report_rash_logs_alert_title" = "%1$@oxirgi marta ishlatilganda qulab tushdi. Biz bilan nosozlik hisobotini baham ko'rmoqchimisiz?"; +"screen_create_room_add_people_title" = "Odamlarni taklif qiling"; +"screen_create_room_room_name_label" = "Xona nomi"; +"screen_create_room_title" = "Xonani yaratish"; +"screen_dm_details_block_alert_action" = "Bloklash"; +"screen_dm_details_block_alert_description" = "Bloklangan foydalanuvchilar sizga xabar yubora olmaydi va ularning barcha xabarlari yashiriladi. Ularni istalgan vaqtda blokdan chiqarishingiz mumkin."; +"screen_dm_details_block_user" = "Foydalanuvchini bloklash"; +"screen_dm_details_unblock_alert_action" = "Blokdan chiqarish"; +"screen_dm_details_unblock_alert_description" = "Ulardan kelgan barcha xabarlarni yana koสปrishingiz mumkin boสปladi."; +"screen_dm_details_unblock_user" = "Foydalanuvchini blokdan chiqarish"; +"screen_edit_poll_delete_confirmation_title" = "Delete Poll"; +"screen_edit_poll_title" = "Soโ€˜rovnomani tahrirlash"; +"screen_identity_use_another_device" = "Use another device"; +"screen_login_subtitle" = "Matrix xavfsiz, markazlashmagan aloqa uchun ochiq tarmoqdir."; +"screen_qr_code_login_invalid_scan_state_retry_button" = "Try again"; +"screen_report_content_block_user" = "Foydalanuvchini bloklash"; +"screen_room_attachment_source_camera_photo" = "Rasmga olmoq"; +"screen_room_change_permissions_everyone" = "Har kim"; +"screen_room_change_permissions_member_moderation" = "Member moderation"; +"screen_room_change_permissions_messages_and_content" = "Messages and content"; +"screen_room_change_permissions_room_details" = "Room details"; +"screen_room_change_role_section_administrators" = "Admins"; +"screen_room_change_role_section_moderators" = "Moderators"; +"screen_room_change_role_section_users" = "Members"; +"screen_room_details_invite_people_title" = "Odamlarni taklif qiling"; +"screen_room_details_leave_conversation_title" = "Leave conversation"; +"screen_room_details_leave_room_title" = "Xonani tark etish"; +"screen_room_details_roles_and_permissions" = "Roles and permissions"; +"screen_room_details_room_name_label" = "Xona nomi"; +"screen_room_details_security_title" = "Xavfsizlik"; +"screen_room_details_topic_title" = "Mavzu"; +"screen_room_error_failed_processing_media" = "Mediani yuklab boโ€˜lmadi, qayta urinib koโ€˜ring."; +"screen_room_notification_settings_mode_mentions_and_keywords" = "Faqat eslatmalar va kalit so'zlar"; +"screen_roomlist_filter_people" = "Odamlar"; +"screen_signout_confirmation_dialog_submit" = "Tizimdan chiqish"; +"screen_signout_confirmation_dialog_title" = "Tizimdan chiqish"; +"screen_signout_preference_item" = "Tizimdan chiqish"; diff --git a/ElementX/Resources/Localizations/uz.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/uz.lproj/Localizable.stringsdict new file mode 100644 index 0000000000..d7c1c72156 --- /dev/null +++ b/ElementX/Resources/Localizations/uz.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 a'zo + other + %1$d ishtirokchilar + + + common_poll_votes_count + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %dovoz berish + other + %dovozlar + + + notification_compat_summary_line_for_room + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@:%2$d xabar + other + %1$@:%2$d xabarlar + + + notification_compat_summary_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %dbildirishnoma + other + %dbildirishnomalar + + + notification_invitations + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %dtaklifnoma + other + %dtaklifnomalar + + + notification_new_messages_for_room + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %dyangi xabar + other + %dyangi xabarlar + + + notification_unread_notified_messages + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %do'qilmagan xabarnoma + other + %do'qilmagan xabarlar + + + notification_unread_notified_messages_in_room_rooms + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %dxona + other + %dxonalar + + + 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$dodam + other + %1$dodamlar + + + screen_room_timeline_state_changes + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$dxonani almashtirish + other + %1$dxona o'zgarishi + + + 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/zh-Hans.lproj/Localizable.strings b/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings index ef8606e91b..a87e1e8a0b 100644 --- a/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings @@ -6,7 +6,7 @@ "a11y_notifications_muted" = "ๅ…ณ้—ญ้€š็Ÿฅ"; "a11y_page_n" = "็ฌฌ %1$d ้กต"; "a11y_pause" = "ๆš‚ๅœ"; -"a11y_pin_field" = "PIN ๆ ไฝ"; +"a11y_pin_field" = "PIN ๅญ—ๆฎต"; "a11y_play" = "ๆ’ญๆ”พ"; "a11y_poll" = "ๆŠ•็ฅจ"; "a11y_poll_end" = "ๆŠ•็ฅจๅทฒ็ป“ๆŸ"; @@ -27,17 +27,20 @@ "action_back" = "่ฟ”ๅ›ž"; "action_call" = "ๅ‘ผๅซ"; "action_cancel" = "ๅ–ๆถˆ"; +"action_cancel_for_now" = "Cancel for now"; "action_choose_photo" = "้€‰ๆ‹ฉ็…ง็‰‡"; "action_clear" = "ๆธ…้™ค"; "action_close" = "ๅ…ณ้—ญ"; "action_complete_verification" = "ๅฎŒๆˆ้ชŒ่ฏ"; "action_confirm" = "็กฎ่ฎค"; +"action_confirm_password" = "Confirm password"; "action_continue" = "็ปง็ปญ"; "action_copy" = "ๅคๅˆถ"; "action_copy_link" = "ๅคๅˆถ้“พๆŽฅ"; "action_copy_link_to_message" = "ๅคๅˆถๆถˆๆฏ้“พๆŽฅ"; "action_create" = "ๅˆ›ๅปบ"; "action_create_a_room" = "ๅˆ›ๅปบๆˆฟ้—ด"; +"action_deactivate" = "Deactivate"; "action_decline" = "ๆ‹’็ป"; "action_delete_poll" = "ๅˆ ้™คๆŠ•็ฅจ"; "action_disable" = "ๅœ็”จ"; @@ -70,16 +73,18 @@ "action_ok" = "ๅฅฝ"; "action_open_settings" = "ๆ‰“ๅผ€่ฎพ็ฝฎ"; "action_open_with" = "็”จๅ…ถไป–ๆ–นๅผๆ‰“ๅผ€"; +"action_pin" = "็ฝฎ้กถ"; "action_quick_reply" = "ๅฟซ้€Ÿๅ›žๅค"; "action_quote" = "ๅผ•็”จ"; "action_react" = "ๅ›žๅบ”"; -"action_reject" = "Reject"; +"action_reject" = "ๆ‹’็ป"; "action_remove" = "็งป้™ค"; "action_reply" = "ๅ›žๅค"; "action_reply_in_thread" = "ๅœจๆถˆๆฏๅˆ—ไธญๅ›žๅค"; "action_report_bug" = "ๆŠฅๅ‘Š้”™่ฏฏ"; "action_report_content" = "ไธพๆŠฅๅ†…ๅฎน"; "action_reset" = "้‡็ฝฎ"; +"action_reset_identity" = "้‡็ฝฎ่บซไปฝ"; "action_retry" = "้‡่ฏ•"; "action_retry_decryption" = "้‡่ฏ•่งฃๅฏ†"; "action_save" = "ไฟๅญ˜"; @@ -99,10 +104,18 @@ "action_take_photo" = "ๆ‹ๆ‘„็…ง็‰‡"; "action_tap_for_options" = "็‚นๆŒ‰ๆŸฅ็œ‹้€‰้กน"; "action_try_again" = "ๅ†่ฏ•ไธ€ๆฌก"; -"action_view_source" = "ๆŸฅ็œ‹ๆฅๆบ"; +"action_unpin" = "ๅ–ๆถˆ็ฝฎ้กถ"; +"action_view_in_timeline" = "View in timeline"; +"action_view_source" = "ๆŸฅ็œ‹ๆบ็ "; "action_yes" = "ๆ˜ฏ"; "action.load_more" = "่ฝฝๅ…ฅๆ›ดๅคš"; -"action.pin" = "Pin"; +"action_deactivate_account" = "Deactivate account"; +"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" = "Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices."; +"banner.set_up_recovery.title" = "Set up recovery"; "common_about" = "ๅ…ณไบŽ"; "common_acceptable_use_policy" = "ๅฏๆŽฅๅ—็š„ไฝฟ็”จๆ”ฟ็ญ–"; "common_advanced_settings" = "้ซ˜็บง่ฎพ็ฝฎ"; @@ -171,7 +184,7 @@ "common_rich_text_editor" = "ๅฏŒๆ–‡ๆœฌ็ผ–่พ‘ๅ™จ"; "common_room" = "ๆˆฟ้—ด"; "common_room_name" = "ๆˆฟ้—ดๅ็งฐ"; -"common_room_name_placeholder" = "ไพ‹ๅฆ‚๏ผšไฝ ็š„้กน็›ฎๅ็งฐ"; +"common_room_name_placeholder" = "ไพ‹ๅฆ‚๏ผš้กน็›ฎๅ็งฐ"; "common_saved_changes" = "ไฟๅญ˜็š„ๆ›ดๆ”น"; "common_saving" = "ๆญฃๅœจไฟๅญ˜"; "common_screen_lock" = "ๅฑๅน•้”ๅฎš"; @@ -209,32 +222,33 @@ "common_verification_cancelled" = "้ชŒ่ฏๅทฒๅ–ๆถˆ"; "common_verification_complete" = "้ชŒ่ฏๅฎŒๆˆ"; "common_video" = "่ง†้ข‘"; -"common_voice_message" = "่ฏญ้Ÿณ็•™่จ€"; +"common_voice_message" = "่ฏญ้Ÿณๆถˆๆฏ"; "common_waiting" = "็ญ‰ๅพ…..."; "common_waiting_for_decryption_key" = "ๆญฃๅœจ็ญ‰ๅพ…่งฃๅฏ†ๅฏ†้’ฅ"; -"common.do_not_show_this_again" = "Do not show this again"; -"common.open_source_licenses" = "Open source licenses"; -"common.send_to" = "Send to"; +"common.do_not_show_this_again" = "ไธๅ†ๆ˜พ็คบๆญคๅ†…ๅฎน"; +"common.open_source_licenses" = "ๅผ€ๆบ่ฎธๅฏ่ฏ"; +"common.pinned" = "Pinned"; +"common.send_to" = "ๅ‘้€่‡ณ"; "common_no_room_name" = "ๆ— ๆˆฟ้—ดๅ"; -"common_poll_end_confirmation" = "ไฝ ็กฎๅฎš่ฆ็ป“ๆŸ่ฟ™ไธชๆŠ•็ฅจๅ—๏ผŸ"; +"common_poll_end_confirmation" = "็กฎๅฎš่ฆ็ป“ๆŸ่ฟ™ไธชๆŠ•็ฅจๅ—๏ผŸ"; "common_poll_summary" = "ๆŠ•็ฅจ๏ผš%1$@"; "common_something_went_wrong" = "ๅ‘็”Ÿไบ†ไธ€ไบ›้”™่ฏฏ"; -"common_unable_to_decrypt_no_access" = "ไฝ ๆ— ๆƒ่ฎฟ้—ฎๆญคๆถˆๆฏ"; +"common_unable_to_decrypt_no_access" = "ๆ— ๆƒ่ฎฟ้—ฎๆญคๆถˆๆฏ"; "common_verify_device" = "้ชŒ่ฏ่ฎพๅค‡"; -"confirm_recovery_key_banner_message" = "ๆ‚จ็š„่Šๅคฉๅค‡ไปฝๅฝ“ๅ‰ไธๅŒๆญฅใ€‚ๆ‚จ้œ€่ฆ่พ“ๅ…ฅๆขๅคๅฏ†้’ฅๆ‰่ƒฝ่ฎฟ้—ฎ่Šๅคฉๅค‡ไปฝใ€‚"; -"confirm_recovery_key_banner_title" = "่พ“ๅ…ฅๆ‚จ็š„ๆขๅคๅฏ†้’ฅ"; -"crash_detection_dialog_content" = "%1$@ ไธŠๆฌกไฝฟ็”จๆ—ถๅดฉๆบƒไบ†ใ€‚ไฝ ๆƒณๅ’Œๆˆ‘ไปฌๅˆ†ไบซๅดฉๆบƒๆŠฅๅ‘Šๅ—๏ผŸ"; +"confirm_recovery_key_banner_message" = "่Šๅคฉๅค‡ไปฝ็›ฎๅ‰ไธๅŒๆญฅ๏ผŒ้œ€่ฆ่พ“ๅ…ฅๆขๅคๅฏ†้’ฅๆ‰่ƒฝ่ฎฟ้—ฎ่Šๅคฉๅค‡ไปฝใ€‚"; +"confirm_recovery_key_banner_title" = "่พ“ๅ…ฅๆขๅคๅฏ†้’ฅ"; +"crash_detection_dialog_content" = "%1$@ ไธŠๆฌกไฝฟ็”จๆ—ถๅดฉๆบƒไบ†ใ€‚ๆƒณๅ’Œๆˆ‘ไปฌๅˆ†ไบซๅดฉๆบƒๆŠฅๅ‘Šๅ—๏ผŸ"; "dialog_permission_camera" = "ไธบไบ†่ฎฉๅบ”็”จ็จ‹ๅบไฝฟ็”จ็›ธๆœบ๏ผŒ่ฏทๅœจ็ณป็ปŸ่ฎพ็ฝฎไธญๆŽˆไบˆๆƒ้™ใ€‚"; "dialog_permission_generic" = "่ฏทๅœจ็ณป็ปŸ่ฎพ็ฝฎไธญๆŽˆไบˆๆƒ้™ใ€‚"; "dialog_permission_location_description_ios" = "ๅœจ่ฎพ็ฝฎ->ไฝ็ฝฎไธญๆŽˆไบˆ่ฎฟ้—ฎๆƒ้™ใ€‚"; "dialog_permission_location_title_ios" = "%1$@ ๆ— ๆƒ่ฎฟ้—ฎๆ‚จ็š„ไฝ็ฝฎใ€‚"; "dialog_permission_microphone" = "ไธบไบ†่ฎฉๅบ”็”จ็จ‹ๅบไฝฟ็”จ้บฆๅ…‹้ฃŽ๏ผŒ่ฏทๅœจ็ณป็ปŸ่ฎพ็ฝฎไธญๆŽˆไบˆๆƒ้™ใ€‚"; -"dialog_permission_microphone_description_ios" = "ๆŽˆไบˆ่ฎฟ้—ฎๆƒ้™๏ผŒ่ฟ™ๆ ทๆ‚จๅฐฑๅฏไปฅๅฝ•ๅˆถๅ‘้€้Ÿณ้ข‘ๆถˆๆฏใ€‚"; +"dialog_permission_microphone_description_ios" = "ๆŽˆไบˆ่ฎฟ้—ฎๆƒ้™ไปฅไพฟๅฝ•ๅˆถๅ’Œๅ‘้€้Ÿณ้ข‘ๆถˆๆฏใ€‚"; "dialog_permission_microphone_title_ios" = "%1$@ ้œ€่ฆๆƒ้™ๆ‰่ƒฝ่ฎฟ้—ฎ้บฆๅ…‹้ฃŽใ€‚"; "dialog_permission_notification" = "ไธบไบ†่ฎฉๅบ”็”จ็จ‹ๅบๆ˜พ็คบ้€š็Ÿฅ๏ผŒ่ฏทๅœจ็ณป็ปŸ่ฎพ็ฝฎไธญๆŽˆไบˆๆƒ้™ใ€‚"; "dialog_title_confirmation" = "็กฎ่ฎค"; "dialog_title_warning" = "่ญฆๅ‘Š"; -"dialog_unsaved_changes_description_ios" = "ๆ‚จ็š„ๆ›ดๆ”นไธไผšไฟๅญ˜"; +"dialog_unsaved_changes_description_ios" = "ๆ›ดๆ”นไธไผšไฟๅญ˜"; "dialog_unsaved_changes_title" = "ไฟๅญ˜ๆ›ดๆ”น๏ผŸ"; "emoji_picker_category_activity" = "ๆดปๅŠจ"; "emoji_picker_category_flags" = "ๆ——ๅธœ"; @@ -244,42 +258,48 @@ "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_failed_creating_the_permalink" = "ๅˆ›ๅปบๅ›บๅฎš้“พๆŽฅๅคฑ่ดฅ"; "error_failed_loading_map" = "%1$@ ๆ— ๆณ•ๅŠ ่ฝฝๅœฐๅ›พ๏ผŒ่ฏท็จๅŽๅ†่ฏ•ใ€‚"; "error_failed_loading_messages" = "ๅŠ ่ฝฝๆถˆๆฏๅคฑ่ดฅ"; "error_failed_locating_user" = "%1$@ ๆ— ๆณ•่ฎฟ้—ฎๆ‚จ็š„ไฝ็ฝฎ๏ผŒ่ฏท็จๅŽๅ†่ฏ•ใ€‚"; -"error_failed_uploading_voice_message" = "ๆ— ๆณ•ไธŠไผ ไฝ ็š„่ฏญ้Ÿณ็•™่จ€ใ€‚"; +"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" = "The authenticity of this encrypted message can't be guaranteed on this device."; -"event_shield_reason_unknown_device" = "Encrypted by an unknown or deleted device."; -"event_shield_reason_unsigned_device" = "Encrypted by a device not verified by its owner."; -"event_shield_reason_unverified_identity" = "Encrypted by an unverified user."; -"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_title" = "Enhance your call experience"; +"event_shield_reason_authenticity_not_guaranteed" = "ๆญคๅŠ ๅฏ†ๆถˆๆฏ็š„็œŸๅฎžๆ€งๆ— ๆณ•ๅœจๆญค่ฎพๅค‡ไธŠไฟ่ฏใ€‚"; +"event_shield_reason_previously_verified" = "Encrypted by a previously-verified user."; +"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" = "ไฝ ็กฎๅฎš่ฆ็ฆปๅผ€่ฟ™ไธชๆˆฟ้—ดๅ—๏ผŸ่ฟ™ไธชๆˆฟ้—ดไธๆ˜ฏๅ…ฌๅผ€็š„๏ผŒๅฆ‚ๆžœๆฒกๆœ‰้‚€่ฏท๏ผŒไฝ ๅฐ†ๆ— ๆณ•้‡ๆ–ฐๅŠ ๅ…ฅใ€‚"; -"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" = "็›‘ๅฌไบ‹ไปถ"; "notification_channel_noisy" = "ๅ˜ˆๆ‚้€š็Ÿฅ"; -"notification_channel_ringing_calls" = "Ringing calls"; +"notification_channel_ringing_calls" = "ๆฅ็”ตๆŒฏ้“ƒ"; "notification_channel_silent" = "้™้ป˜้€š็Ÿฅ"; -"notification_incoming_call" = "Incoming call"; +"notification_incoming_call" = "ๆฅ็”ต"; "notification_inline_reply_failed" = "** ๆ— ๆณ•ๅ‘้€โ€”โ€”่ฏทๆ‰“ๅผ€ๆˆฟ้—ด"; "notification_invitation_action_reject" = "ๆ‹’็ป"; "notification_invite_body" = "้‚€่ฏทๆ‚จ่Šๅคฉ"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "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_sender_me" = "ๆˆ‘"; +"notification_sender_mention_reply" = "%1$@ mentioned or replied"; "notification_test_push_notification_content" = "ๆ‚จๆญฃๅœจๆŸฅ็œ‹้€š็Ÿฅ๏ผ็‚นๅ‡ปๆˆ‘๏ผ"; "notification_ticker_text_dm" = "%1$@๏ผš%2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -309,13 +329,30 @@ "rich_text_editor_unindent" = "ๅ–ๆถˆ็ผฉ่ฟ›"; "rich_text_editor_url_placeholder" = "้“พๆŽฅ"; "rich_text_editor_a11y_add_attachment" = "ๆทปๅŠ ้™„ไปถ"; -"screen_advanced_settings_element_call_base_url" = "่‡ชๅฎšไน‰ Element ้€š่ฏ URL"; +"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_pinned_timeline_empty_state_description" = "ๆŒ‰ไธ‹ๆถˆๆฏๅนถ้€‰ๆ‹ฉ โ€œ%1$@โ€ ๅฐ†ๅ…ถๅŒ…ๅซๅœจๆญคๅค„ใ€‚"; +"screen_pinned_timeline_empty_state_headline" = "ๅ›บๅฎš้‡่ฆๆถˆๆฏ๏ผŒไปฅไพฟ่ฝปๆพๅ‘็Žฐๅฎƒไปฌ"; +"screen_pinned_timeline_screen_title_empty" = "็ฝฎ้กถๆถˆๆฏ"; +"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.room.pinned_banner_indicator" = "%1$@ of %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ Pinned messages"; -"screen.room.pinned_banner_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_details_pinned_events_row_title" = "็ฝฎ้กถๆถˆๆฏ"; +"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_account_provider_change" = "ๆ›ดๆ”น่ดฆๆˆทๆไพ›่€…"; "screen_account_provider_form_hint" = "ๆœๅŠกๅ™จๅœฐๅ€"; "screen_account_provider_form_notice" = "่พ“ๅ…ฅๆœ็ดข่ฏๆˆ–ๅŸŸๅๅœฐๅ€ใ€‚"; @@ -330,12 +367,12 @@ "screen_advanced_settings_send_read_receipts_description" = "ๅฆ‚ๆžœๅ…ณ้—ญ๏ผŒๆ‚จ็š„ๅทฒ่ฏปๅ›žๆ‰งๅฐ†ไธไผšๅ‘้€็ป™ๅˆซไบบใ€‚ๆ‚จไป่ƒฝๆ”ถๅˆฐๅˆซไบบ็š„ๅทฒ่ฏปๅ›žๆ‰งใ€‚"; "screen_advanced_settings_share_presence" = "ๅˆ†ไบซๅœจ็บฟ็Šถๆ€"; "screen_advanced_settings_share_presence_description" = "ๅฆ‚ๆžœๅ…ณ้—ญ๏ผŒๆ‚จๅฐ†ๆ— ๆณ•ๅ‘้€ๆˆ–ๆŽฅๆ”ถๅทฒ่ฏปๅ›žๆ‰งใ€่พ“ๅ…ฅ้€š็Ÿฅ"; -"screen_advanced_settings_view_source_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_settings" = "ๅฏไปฅ้šๆ—ถๅ…ณ้—ญๆญคๅŠŸ่ƒฝ"; "screen_analytics_prompt_third_party_sharing" = "ๆˆ‘ไปฌไธไผšไธŽ็ฌฌไธ‰ๆ–นๅ…ฑไบซๆ‚จ็š„ๆ•ฐๆฎ"; "screen_analytics_prompt_title" = "ๅธฎๅŠฉๆ”น่ฟ› %1$@"; "screen_analytics_settings_share_data" = "ๅ…ฑไบซๅˆ†ๆžๆ•ฐๆฎ"; @@ -382,11 +419,11 @@ "screen_change_account_provider_other" = "ๅ…ถไป–"; "screen_change_account_provider_subtitle" = "ไฝฟ็”จๅ…ถไป–ๅธๆˆทๆไพ›่€…๏ผŒไพ‹ๅฆ‚ๆ‚จ่‡ชๅทฑ็š„็งไบบๆœๅŠกๅ™จๆˆ–ๅทฅไฝœๅธๆˆทใ€‚"; "screen_change_account_provider_title" = "ๆ›ดๆ”น่ดฆๆˆทๆไพ›่€…"; -"screen_change_server_error_invalid_homeserver" = "ๆˆ‘ไปฌๆ— ๆณ•่ฎฟ้—ฎๆญคไธปๆœๅŠกๅ™จใ€‚่ฏทๆฃ€ๆŸฅๆ‚จ่พ“ๅ…ฅ็š„ไธปๆœๅŠกๅ™จ็ฝ‘ๅ€ๆ˜ฏๅฆๆญฃ็กฎใ€‚ๅฆ‚ๆžœ URL ๆญฃ็กฎ๏ผŒ่ฏท่”็ณปๆ‚จ็š„ไธปๆœๅŠกๅ™จ็ฎก็†ๅ‘˜ๅฏปๆฑ‚่ฟ›ไธ€ๆญฅๅธฎๅŠฉใ€‚"; +"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ใ€‚"; -"screen_change_server_form_header" = "ไธปๆœๅŠกๅ™จ็ฝ‘ๅ€"; -"screen_change_server_form_notice" = "ๆ‚จๅช่ƒฝ่ฟžๆŽฅๅˆฐๆ”ฏๆŒsliding sync็š„็Žฐๆœ‰ๆœๅŠกๅ™จใ€‚ๆ‚จ็š„ไธปๆœๅŠกๅ™จ็ฎก็†ๅ‘˜้œ€่ฆๅฏนๅ…ถ่ฟ›่กŒ้…็ฝฎใ€‚%1$@"; +"screen_change_server_error_no_sliding_sync_message" = "่ฏฅๆœๅŠกๅ™จ็›ฎๅ‰ไธๆ”ฏๆŒ Sliding Syncใ€‚"; +"screen_change_server_form_header" = "ๆœๅŠกๅ™จ็ฝ‘ๅ€"; +"screen_change_server_form_notice" = "ๆ‚จๅช่ƒฝ่ฟžๆŽฅๅˆฐๆ”ฏๆŒ Sliding Sync ็š„็Žฐๆœ‰ๆœๅŠกๅ™จใ€‚ๆ‚จ็š„ๆœๅŠกๅ™จ็ฎก็†ๅ‘˜้œ€่ฆๅฏนๅ…ถ่ฟ›่กŒ้…็ฝฎใ€‚%1$@"; "screen_change_server_subtitle" = "ๆ‚จ็š„ๆœๅŠกๅ™จๅœฐๅ€ๆ˜ฏไป€ไนˆ๏ผŸ"; "screen_change_server_title" = "้€‰ๆ‹ฉๆœๅŠกๅ™จ"; "screen_chat_backup_key_backup_action_disable" = "ๅ…ณ้—ญๅค‡ไปฝ"; @@ -398,6 +435,7 @@ "screen_chat_backup_recovery_action_confirm_description" = "ๆ‚จ็š„่Šๅคฉๅค‡ไปฝๅฝ“ๅ‰ไธๅŒๆญฅใ€‚"; "screen_chat_backup_recovery_action_setup" = "่ฎพ็ฝฎๆขๅคๅฏ†้’ฅ"; "screen_chat_backup_recovery_action_setup_description" = "ๅœจไธขๅคฑๆˆ–ไปŽ %1$@ ็™ปๅ‡บๆ‰€ๆœ‰่ฎพๅค‡็š„ๆƒ…ๅ†ตไธ‹่ฎฟ้—ฎๅŠ ๅฏ†ๆถˆๆฏใ€‚"; +"screen_create_account_title" = "Create account"; "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$@"; @@ -418,9 +456,20 @@ "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_description" = "ๆถˆๆฏๆœชๅŠ ๅฏ†๏ผŒไปปไฝ•ไบบ้ƒฝๅฏไปฅๆŸฅ็œ‹ใ€‚ๅฏไปฅ็จๅŽๅฏ็”จๅŠ ๅฏ†ใ€‚"; "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_edit_poll_delete_confirmation" = "ๆ‚จ็กฎๅฎš่ฆๅˆ ้™คๆญคๆŠ•็ฅจๅ—๏ผŸ"; "screen_edit_profile_display_name" = "ๆ˜พ็คบๅ็งฐ"; "screen_edit_profile_display_name_placeholder" = "ไฝ ็š„ๆ˜พ็คบๅ็งฐ"; @@ -428,12 +477,20 @@ "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_bullet_2" = "ๆ‚จๅฐ†ไธขๅคฑ็Žฐๆœ‰็š„ๆถˆๆฏๅŽ†ๅฒ่ฎฐๅฝ•"; +"screen_encryption_reset_bullet_3" = "ๆ‚จๅฐ†้œ€่ฆๅ†ๆฌก้ชŒ่ฏๆ‰€ๆœ‰ๆ‚จ็š„็Žฐๆœ‰่ฎพๅค‡ๅ’Œ่”็ณปไบบ"; +"screen_encryption_reset_footer" = "ไป…ๅฝ“ๆ‚จๆ— ๆณ•่ฎฟ้—ฎๅ…ถไป–ๅทฒ็™ปๅฝ•่ฎพๅค‡ๅนถไธ”ไธขๅคฑไบ†ๆขๅคๅฏ†้’ฅๆ—ถๆ‰้‡็ฝฎๆ‚จ็š„่บซไปฝใ€‚"; +"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" = "ไฝฟ็”จๅ…ถไป–่ฎพๅค‡"; +"screen_identity_confirmation_use_recovery_key" = "ไฝฟ็”จๆขๅคๅฏ†้’ฅ"; "screen_identity_confirmed_subtitle" = "็Žฐๅœจ๏ผŒๆ‚จๅฏไปฅๅฎ‰ๅ…จๅœฐ้˜…่ฏปๆˆ–ๅ‘้€ๆถˆๆฏ๏ผŒไธŽๆ‚จ่Šๅคฉ็š„ไบบไนŸไผšไฟกไปปๆญค่ฎพๅค‡ใ€‚"; "screen_identity_confirmed_title" = "่ฎพๅค‡ๅทฒ้ชŒ่ฏ"; -"screen_identity_use_another_device" = "ไฝฟ็”จๅ…ถไป–่ฎพๅค‡"; "screen_identity_waiting_on_other_device" = "ๆญฃๅœจ็ญ‰ๅพ…ๅ…ถไป–่ฎพๅค‡โ€ฆโ€ฆ"; "screen_invites_decline_chat_message" = "ๆ‚จ็กฎๅฎš่ฆๆ‹’็ปๅŠ ๅ…ฅ %1$@ ็š„้‚€่ฏทๅ—๏ผŸ"; "screen_invites_decline_chat_title" = "ๆ‹’็ป้‚€่ฏท"; @@ -454,7 +511,7 @@ "screen_key_backup_disable_confirmation_title" = "ๆ‚จ็กฎๅฎš่ฆๅ…ณ้—ญๅค‡ไปฝๅ—๏ผŸ"; "screen_key_backup_disable_description" = "ๅ…ณ้—ญๅค‡ไปฝๅฐ†ๅˆ ้™คๆ‚จๅฝ“ๅ‰็š„ๅŠ ๅฏ†ๅฏ†้’ฅๅค‡ไปฝๅนถๅ…ณ้—ญๅ…ถไป–ๅฎ‰ๅ…จๅŠŸ่ƒฝใ€‚ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฐ†๏ผš"; "screen_key_backup_disable_description_point_1" = "ๆ–ฐ่ฎพๅค‡ไธŠๆฒกๆœ‰ๅŠ ๅฏ†ๆถˆๆฏ็š„ๅŽ†ๅฒ่ฎฐๅฝ•"; -"screen_key_backup_disable_description_point_2" = "ๅฆ‚ๆžœๆ‚จๅœจๆ‰€ๆœ‰่ฎพๅค‡ไธŠ็™ปๅ‡บไบ† %1$@๏ผŒ้‚ฃๅฐ†ๆ— ๆณ•่ฎฟ้—ฎๅŠ ๅฏ†็š„ๆถˆๆฏ"; +"screen_key_backup_disable_description_point_2" = "ๅฆ‚ๆžœๆ‚จๅœจๆ‰€ๆœ‰่ฎพๅค‡ไธŠ็™ปๅ‡บไบ† %1$@๏ผŒ้‚ฃๅฐ†ๆ— ๆณ•่ฎฟ้—ฎๅŠ ๅฏ†ๆถˆๆฏ"; "screen_key_backup_disable_title" = "ๆ‚จ็กฎๅฎš่ฆๅ…ณ้—ญๅค‡ไปฝๅ—๏ผŸ"; "screen_login_error_deactivated_account" = "่ฏฅ่ดฆๆˆทๅทฒ่ขซๅœ็”จใ€‚"; "screen_login_error_invalid_credentials" = "้”™่ฏฏ็š„็”จๆˆทๅๅ’Œ/ๆˆ–ๅฏ†็ "; @@ -511,13 +568,13 @@ "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" = "ๅฆ‚ๆžœ่ฟ™ๆ˜ฏ็ฝ‘็ปœ้—ฎ้ข˜๏ผŒ่ฏทๅฐ่ฏ•ไฝฟ็”จไบŒ็ปด็ ๅ†ๆฌก็™ปๅฝ•"; -"screen_qr_code_login_connection_note_secure_state_list_item_2" = "ๅฆ‚ๆžœไฝ ้‡ๅˆฐๅŒๆ ท็š„้—ฎ้ข˜๏ผŒ่ฏทๅฐ่ฏ•ไฝฟ็”จไธๅŒ็š„ WiFi ็ฝ‘็ปœๆˆ–ไฝฟ็”จไฝ ็š„็งปๅŠจๆ•ฐๆฎไปฃๆ›ฟ WiFi"; +"screen_qr_code_login_connection_note_secure_state_list_item_2" = "ๅฆ‚ๆžœ้‡ๅˆฐๅŒๆ ท็š„้—ฎ้ข˜๏ผŒ่ฏทๅฐ่ฏ•ไฝฟ็”จไธๅŒ็š„ WiFi ็ฝ‘็ปœๆˆ–ไฝฟ็”จ็งปๅŠจๆ•ฐๆฎไปฃๆ›ฟ WiFi"; "screen_qr_code_login_connection_note_secure_state_list_item_3" = "ๅฆ‚ๆžœไธ่ตทไฝœ็”จ๏ผŒ่ฏทๆ‰‹ๅŠจ็™ปๅฝ•"; "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" = "Sign in to your other device and then try again, or use another device thatโ€™s already signed in."; -"screen_qr_code_login_device_not_signed_in_scan_state_subtitle" = "Other device not signed in"; +"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" = "ๅ…ถๅฎƒ่ฎพๅค‡ๆœชๆŽฅๅ—่ฏทๆฑ‚"; @@ -556,7 +613,6 @@ "screen_recovery_key_confirm_error_content" = "่ฏท้‡่ฏ•ไปฅ่ฎฟ้—ฎๆ‚จ็š„่Šๅคฉๅค‡ไปฝใ€‚"; "screen_recovery_key_confirm_error_title" = "ๆขๅคๅฏ†้’ฅไธๆญฃ็กฎ"; "screen_recovery_key_confirm_key_description" = "ๅฆ‚ๆžœๆ‚จๆœ‰ๅฎ‰ๅ…จๅฏ†้’ฅๆˆ–ๅฎ‰ๅ…จ็Ÿญ่ฏญ๏ผŒไนŸๅฏไปฅ็”จใ€‚"; -"screen_recovery_key_confirm_key_label" = "ๆขๅคๅฏ†้’ฅๆˆ–ๅฏ†็ "; "screen_recovery_key_confirm_key_placeholder" = "่พ“ๅ…ฅโ€ฆโ€ฆ"; "screen_recovery_key_confirm_lost_recovery_key" = "ไธขๅคฑไบ†ๆขๅคๅฏ†้’ฅ๏ผŸ"; "screen_recovery_key_confirm_success" = "ๆขๅคๅฏ†้’ฅๅทฒ็กฎ่ฎค"; @@ -575,8 +631,16 @@ "screen_recovery_key_setup_success" = "ๆขๅค่ฎพ็ฝฎๆˆๅŠŸ"; "screen_recovery_key_setup_title" = "่ฎพ็ฝฎๆขๅค"; "screen_report_content_block_user_hint" = "่ฏท็กฎ่ฎคๆ˜ฏๅฆ่ฆ้š่—่ฏฅ็”จๆˆทๅฝ“ๅ‰ๅ’Œๆœชๆฅ็š„ๆ‰€ๆœ‰ไฟกๆฏ"; -"screen_report_content_explanation" = "ๆญคๆถˆๆฏๅฐ†ไธพๆŠฅ็ป™ๆ‚จ็š„ไธปๆœๅŠกๅ™จ็ฎก็†ๅ‘˜ใ€‚ไป–ไปฌๆ— ๆณ•่ฏปๅ–ไปปไฝ•ๅŠ ๅฏ†ๆถˆๆฏใ€‚"; +"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_placeholder" = "่พ“ๅ…ฅ..."; +"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_room_alias_resolver_resolve_alias_failure" = "ๆ— ๆณ•่งฃๆžๆˆฟ้—ดๅˆซๅใ€‚"; "screen_room_attachment_source_camera" = "็›ธๆœบ"; "screen_room_attachment_source_camera_video" = "ๅฝ•ๅˆถ่ง†้ข‘"; @@ -615,7 +679,7 @@ "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" = "ๆ— ๆณ•ๅฐ†ๆญคๆˆฟ้—ด้™้Ÿณ๏ผŒ่ฏท้‡่ฏ•ใ€‚"; @@ -638,7 +702,7 @@ "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_alert_description" = "ๅฏไปฅ้‡ๆ–ฐๆŽฅๆ”ถไป–ไปฌ็š„ๆถˆๆฏใ€‚"; "screen_room_member_details_unblock_user" = "่งฃๅฐ็”จๆˆท"; "screen_room_member_list_ban_member_confirmation_action" = "ๅฐ็ฆ"; "screen_room_member_list_ban_member_confirmation_description" = "ๅณไฝฟๅ—ๅˆฐ้‚€่ฏท๏ผŒไป–ไปฌไนŸๆ— ๆณ•ๅ†ๆฌกๅŠ ๅ…ฅๆˆฟ้—ดใ€‚"; @@ -675,7 +739,7 @@ "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" = "้‡ๆ–ฐๅ‘้€"; +"screen_room_retry_send_menu_send_again_action" = "ๅ†ๆฌกๅ‘้€"; "screen_room_retry_send_menu_title" = "ๆถˆๆฏๅ‘้€ๅคฑ่ดฅ"; "screen_room_roles_and_permissions_admins" = "็ฎก็†ๅ‘˜"; "screen_room_roles_and_permissions_change_my_role" = "ๆ›ดๆ”นๆˆ‘็š„่ง’่‰ฒ"; @@ -710,10 +774,10 @@ "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_subtitle" = "ๅฏไปฅๅœจ่Šๅคฉ่ฎพ็ฝฎ้‡Œๅฐ†่ŠๅคฉๆทปๅŠ ๅˆฐๆ”ถ่—ๅคนไธญใ€‚\n็Žฐๅœจ๏ผŒๅฏไปฅๅ–ๆถˆ้€‰ๆ‹ฉ่ฟ‡ๆปคๅ™จไปฅๆŸฅ็œ‹ๅ…ถไป–ๅฏน่ฏใ€‚"; "screen_roomlist_filter_favourites_empty_state_title" = "ๆ‚จๆœชๆ”ถ่—ไปปไฝ•่Šๅคฉ"; "screen_roomlist_filter_invites" = "้‚€่ฏท"; -"screen_roomlist_filter_invites_empty_state_title" = "ไฝ ๆฒกๆœ‰ไปปไฝ•ๅพ…ๅค„็†็š„้‚€่ฏทใ€‚"; +"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" = "ๆ‚จๆฒกๆœ‰ๅ…ณไบŽๆญค้€‰้กน็š„่Šๅคฉ"; @@ -721,7 +785,7 @@ "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_filter_unreads_empty_state_title" = "ๆญๅ–œ๏ผ\nๆฒกๆœ‰ไปปไฝ•ๆœช่ฏปๆถˆๆฏ๏ผ"; "screen_roomlist_main_space_title" = "ๅ…จ้ƒจ่Šๅคฉ"; "screen_roomlist_mark_as_read" = "ๆ ‡่ฎฐไธบๅทฒ่ฏป"; "screen_roomlist_mark_as_unread" = "ๆ ‡่ฎฐไธบๆœช่ฏป"; @@ -730,14 +794,14 @@ "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_title_login" = "ไฝ ๅณๅฐ†็™ปๅฝ• %1$@"; -"screen_server_confirmation_title_register" = "ไฝ ๅณๅฐ†ๅœจ %1$@ ไธŠๅˆ›ๅปบไธ€ไธช่ดฆๆˆท"; +"screen_server_confirmation_title_login" = "ๅณๅฐ†็™ปๅฝ• %1$@"; +"screen_server_confirmation_title_register" = "ๅณๅฐ†ๅœจ %1$@ ไธŠๅˆ›ๅปบไธ€ไธช่ดฆๆˆท"; "screen_session_verification_cancelled_subtitle" = "ๅ‘็”Ÿไบ†ไธ€ไบ›้”™่ฏฏใ€‚็ฝ‘็ปœ่ฏทๆฑ‚่ถ…ๆ—ถ๏ผŒๆˆ–่€…่ขซๆœๅŠกๅ™จๆ‹’็ปใ€‚"; "screen_session_verification_compare_emojis_subtitle" = "็กฎ่ฎคไธ‹ๆ–น็š„่กจๆƒ…็ฌฆๅทไธŽๅฆไธ€่ฎพๅค‡ไธŠๆ˜พ็คบ็š„็›ธๅŒใ€‚"; "screen_session_verification_compare_emojis_title" = "ๆฏ”่พƒ่กจๆƒ…็ฌฆๅท"; "screen_session_verification_compare_numbers_subtitle" = "็กฎ่ฎคไปฅไธ‹ๆ•ฐๅญ—ไธŽๅ…ถไป–ไผš่ฏไธญๆ˜พ็คบ็š„ไธ€่‡ดใ€‚"; "screen_session_verification_compare_numbers_title" = "ๆฏ”่พƒๆ•ฐๅญ—"; -"screen_session_verification_complete_subtitle" = "ไฝ ็š„ๆ–ฐ่ฎพๅค‡ๅทฒ็ปๆˆๅŠŸ้ชŒ่ฏใ€‚็Žฐๅœจๆ–ฐ่ฎพๅค‡ๅฏไปฅ่ฎฟ้—ฎๅŠ ๅฏ†ไฟกๆฏ๏ผŒๅˆซ็š„็”จๆˆทไนŸไผšไฟกไปป่ฟ™ไธช่ฎพๅค‡ใ€‚"; +"screen_session_verification_complete_subtitle" = "ๆ–ฐ่ฎพๅค‡ๅทฒ็ปๆˆๅŠŸ้ชŒ่ฏใ€‚็Žฐๅœจๆ–ฐ่ฎพๅค‡ๅฏไปฅ่ฎฟ้—ฎๅŠ ๅฏ†ไฟกๆฏ๏ผŒๅ…ถไป–็”จๆˆทไนŸไผšไฟกไปป่ฟ™ไธช่ฎพๅค‡ใ€‚"; "screen_session_verification_enter_recovery_key" = "่พ“ๅ…ฅๆขๅคๅฏ†้’ฅ"; "screen_session_verification_open_existing_session_subtitle" = "่ฏๆ˜Ž่‡ชๅทฑ็š„่บซไปฝไปฅ่ฎฟ้—ฎๅŠ ๅฏ†ๅŽ†ๅฒๆถˆๆฏใ€‚"; "screen_session_verification_open_existing_session_title" = "ๆ‰“ๅผ€ๅทฒๆœ‰ไผš่ฏ"; @@ -763,21 +827,18 @@ "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_subtitle" = "ๅณๅฐ†็™ปๅ‡บๆœ€ๅŽไธ€ไธชไผš่ฏใ€‚ๅฆ‚ๆžœ็Žฐๅœจ็™ปๅ‡บ๏ผŒๅฐ†ๆ— ๆณ•่ฎฟ้—ฎๅŠ ๅฏ†็š„ๆถˆๆฏใ€‚"; "screen_signout_key_backup_disabled_title" = "ๆ‚จๅทฒๅ…ณ้—ญๅค‡ไปฝ"; -"screen_signout_key_backup_offline_subtitle" = "ๅฝ“ไฝ ็ฆป็บฟๆ—ถ๏ผŒไฝ ็š„ๅฏ†้’ฅไปๅœจๅค‡ไปฝไธญใ€‚้‡ๆ–ฐ่ฟžๆŽฅ๏ผŒไปฅไพฟๅœจ็™ปๅ‡บไน‹ๅ‰ๅค‡ไปฝๅฏ†้’ฅใ€‚"; +"screen_signout_key_backup_offline_subtitle" = "ๅฝ“ไฝ ็ฆป็บฟๆ—ถ๏ผŒๅฏ†้’ฅไปๅœจๅค‡ไปฝไธญใ€‚้‡ๆ–ฐ่ฟžๆŽฅไปฅไพฟๅœจ็™ปๅ‡บไน‹ๅ‰ๅค‡ไปฝๅฏ†้’ฅใ€‚"; "screen_signout_key_backup_offline_title" = "ๆ‚จ็š„ๅฏ†้’ฅไปๅœจๅค‡ไปฝไธญ"; "screen_signout_key_backup_ongoing_subtitle" = "่ฏท็ญ‰ๅพ…ๆญคๆ“ไฝœๅฎŒๆˆๅŽๅ†็™ปๅ‡บใ€‚"; "screen_signout_key_backup_ongoing_title" = "ๆ‚จ็š„ๅฏ†้’ฅไปๅœจๅค‡ไปฝไธญ"; -"screen_signout_recovery_disabled_subtitle" = "ๆ‚จๅณๅฐ†็™ปๅ‡บๆœ€ๅŽไธ€ไธชไผš่ฏใ€‚ๅฆ‚ๆžœ็Žฐๅœจ็™ปๅ‡บ๏ผŒไฝ ๅฐ†ๆ— ๆณ•่ฎฟ้—ฎๅŠ ๅฏ†็š„ๆถˆๆฏใ€‚"; +"screen_signout_recovery_disabled_subtitle" = "ๅณๅฐ†็™ปๅ‡บๆœ€ๅŽไธ€ไธชไผš่ฏใ€‚ๅฆ‚ๆžœ็Žฐๅœจ็™ปๅ‡บ๏ผŒๅฐ†ๆ— ๆณ•่ฎฟ้—ฎๅŠ ๅฏ†็š„ๆถˆๆฏใ€‚"; "screen_signout_recovery_disabled_title" = "ๆœช่ฎพ็ฝฎๆขๅค"; -"screen_signout_save_recovery_key_subtitle" = "ๆ‚จๅณๅฐ†็™ปๅ‡บๆœ€ๅŽไธ€ไธชไผš่ฏใ€‚ๅฆ‚ๆžœ็Žฐๅœจ็™ปๅ‡บ๏ผŒไฝ ๅฐ†ๆ— ๆณ•่ฎฟ้—ฎๅŠ ๅฏ†็š„ๆถˆๆฏใ€‚"; +"screen_signout_save_recovery_key_subtitle" = "ๅณๅฐ†็™ปๅ‡บๆœ€ๅŽไธ€ไธชไผš่ฏใ€‚ๅฆ‚ๆžœ็Žฐๅœจ็™ปๅ‡บ๏ผŒๅฐ†ๆ— ๆณ•่ฎฟ้—ฎๅŠ ๅฏ†็š„ๆถˆๆฏใ€‚"; "screen_signout_save_recovery_key_title" = "ๆ‚จไฟๅญ˜ไบ†ๆขๅคๅฏ†้’ฅๅ—๏ผŸ"; "screen_start_chat_error_starting_chat" = "ๅœจๅผ€ๅง‹่Šๅคฉๆ—ถๅ‘็”Ÿไบ†้”™่ฏฏ"; "screen_view_location_title" = "ไฝ็ฝฎ"; -"screen_waitlist_message" = "็›ฎๅ‰ %1$@ ไธŠ %2$@ ็š„่ดŸ่ฝฝๅพˆๅคงใ€‚่ฟ‡ๅ‡ ๅคฉๅ†ๅ›žๆฅ่ฏ•่ฏ•ๅงใ€‚\n\nๆ„Ÿ่ฐขๆ‚จ็š„่€ๅฟƒ๏ผ"; -"screen_waitlist_title" = "้ฉฌไธŠๅฐฑๅฅฝใ€‚"; -"screen_waitlist_title_success" = "ๆ‚จๅทฒๅŠ ๅ…ฅใ€‚"; "screen_welcome_bullet_1" = "ไปŠๅนดๆ™šไบ›ๆ—ถๅ€™ๅฐ†ๅขžๅŠ ้€š่ฏใ€ๆŠ•็ฅจใ€ๆœ็ดข็ญ‰ๅŠŸ่ƒฝใ€‚"; "screen_welcome_bullet_2" = "ๅŠ ๅฏ†ๆˆฟ้—ด็š„ๆถˆๆฏๅŽ†ๅฒ่ฎฐๅฝ•ๅฐšไธๅฏ็”จใ€‚"; "screen_welcome_bullet_3" = "ๆˆ‘ไปฌๅพˆไนๆ„ๅฌๅ–ๆ‚จ็š„ๆ„่ง๏ผŒ่ฏท้€š่ฟ‡่ฎพ็ฝฎ้กต้ขๅ‘Š่ฏ‰ๆˆ‘ไปฌๆ‚จ็š„ๆƒณๆณ•ใ€‚"; @@ -834,6 +895,12 @@ "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$@ ๆ›ดๆ”นไบ†็ฝฎ้กถๆถˆๆฏ"; +"state_event_room_pinned_events_changed_by_you" = "ๆ‚จๆ›ดๆ”นไบ†็ฝฎ้กถๆถˆๆฏ"; +"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_by_you" = "ๆ‚จๅ–ๆถˆ็ฝฎ้กถไบ†ไธ€ๆกๆถˆๆฏ"; "state_event_room_reject" = "%1$@ ๆ‹’็ปไบ†้‚€่ฏท"; "state_event_room_reject_by_you" = "ไฝ ๆ‹’็ปไบ†้‚€่ฏท"; "state_event_room_remove" = "%1$@ ็งป้™คไบ† %2$@"; @@ -860,7 +927,7 @@ "troubleshoot_notifications_screen_quick_fix_action" = "ๅฐ่ฏ•ไฟฎๅค"; "troubleshoot_notifications_screen_success" = "ๆ‰€ๆœ‰ๆต‹่ฏ•ๅ‡ๆˆๅŠŸ้€š่ฟ‡ใ€‚"; "troubleshoot_notifications_screen_title" = "ๆŽ’ๆŸฅ้€š็Ÿฅ้—ฎ้ข˜"; -"troubleshoot_notifications_screen_waiting" = "ๆœ‰ไบ›ๆต‹่ฏ•้œ€่ฆไฝ ๆณจๆ„ใ€‚่ฏทๆŸฅ็œ‹่ฏฆๆƒ…ใ€‚"; +"troubleshoot_notifications_screen_waiting" = "ๆœ‰ไบ›ๆต‹่ฏ•้œ€่ฆๆณจๆ„ใ€‚่ฏทๆŸฅ็œ‹่ฏฆๆƒ…ใ€‚"; "troubleshoot_notifications_test_check_permission_description" = "ๆฃ€ๆŸฅๅบ”็”จ็จ‹ๅบๆ˜ฏๅฆๅฏไปฅๆ˜พ็คบ้€š็Ÿฅใ€‚"; "troubleshoot_notifications_test_check_permission_title" = "ๆฃ€ๆŸฅๆƒ้™"; "troubleshoot_notifications_test_current_push_provider_description" = "่Žทๅ–ๅฝ“ๅ‰ๆŽจ้€ๆไพ›่€…็š„ๅ็งฐใ€‚"; @@ -907,9 +974,9 @@ "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_description" = "ๅฏไปฅ้‡ๆ–ฐๆŽฅๆ”ถไป–ไปฌ็š„ๆถˆๆฏใ€‚"; "screen_blocked_users_unblock_alert_title" = "่งฃๅฐ็”จๆˆท"; -"screen_bug_report_rash_logs_alert_title" = "%1$@ ไธŠๆฌกไฝฟ็”จๆ—ถๅดฉๆบƒไบ†ใ€‚ไฝ ๆƒณๅ’Œๆˆ‘ไปฌๅˆ†ไบซๅดฉๆบƒๆŠฅๅ‘Šๅ—๏ผŸ"; +"screen_bug_report_rash_logs_alert_title" = "%1$@ ไธŠๆฌกไฝฟ็”จๆ—ถๅดฉๆบƒไบ†ใ€‚ๆƒณๅ’Œๆˆ‘ไปฌๅˆ†ไบซๅดฉๆบƒๆŠฅๅ‘Šๅ—๏ผŸ"; "screen_create_room_add_people_title" = "้‚€่ฏทๆœ‹ๅ‹"; "screen_create_room_room_name_label" = "ๆˆฟ้—ดๅ็งฐ"; "screen_create_room_title" = "ๅˆ›ๅปบๆˆฟ้—ด"; @@ -917,10 +984,11 @@ "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_alert_description" = "ๅฏไปฅ้‡ๆ–ฐๆŽฅๆ”ถไป–ไปฌ็š„ๆถˆๆฏใ€‚"; "screen_dm_details_unblock_user" = "่งฃๅฐ็”จๆˆท"; "screen_edit_poll_delete_confirmation_title" = "ๅˆ ้™คๆŠ•็ฅจ"; "screen_edit_poll_title" = "็ผ–่พ‘ๆŠ•็ฅจ"; +"screen_identity_use_another_device" = "ไฝฟ็”จๅ…ถไป–่ฎพๅค‡"; "screen_login_subtitle" = "Matrix ๆ˜ฏไธ€ไธช็”จไบŽๅฎ‰ๅ…จใ€ๅŽปไธญๅฟƒๅŒ–้€šไฟก็š„ๅผ€ๆ”พ็ฝ‘็ปœใ€‚"; "screen_qr_code_login_invalid_scan_state_retry_button" = "ๅ†่ฏ•ไธ€ๆฌก"; "screen_report_content_block_user" = "ๅฐ็ฆ็”จๆˆท"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "็™ปๅ‡บ"; "screen_signout_confirmation_dialog_title" = "็™ปๅ‡บ"; "screen_signout_preference_item" = "็™ปๅ‡บ"; -"screen_waitlist_message_success" = "ๆฌข่ฟŽไฝฟ็”จ %1$@"; diff --git a/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.stringsdict index 94f079617d..dd12b72dad 100644 --- a/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.stringsdict @@ -170,6 +170,20 @@ PIN ็ ้”™่ฏฏใ€‚่ฟ˜ๅ‰ฉ %1$d ๆฌกๆœบไผš + screen_pinned_timeline_screen_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + other + %1$d ็ฝฎ้กถๆถˆๆฏ + + screen_room_member_list_header_title NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings b/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings index 68283c1ff2..42aeacb27e 100644 --- a/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings @@ -27,17 +27,20 @@ "action_back" = "่ฟ”ๅ›ž"; "action_call" = "้€š่ฉฑ"; "action_cancel" = "ๅ–ๆถˆ"; +"action_cancel_for_now" = "Cancel for now"; "action_choose_photo" = "้ธๆ“‡็…ง็‰‡"; "action_clear" = "ๆธ…้™ค"; "action_close" = "้—œ้–‰"; "action_complete_verification" = "ๅฎŒๆˆ้ฉ—่ญ‰"; "action_confirm" = "็ขบ่ช"; +"action_confirm_password" = "Confirm password"; "action_continue" = "็นผ็บŒ"; "action_copy" = "่ค‡่ฃฝ"; "action_copy_link" = "่ค‡่ฃฝ้€ฃ็ต"; "action_copy_link_to_message" = "่ค‡่ฃฝ่จŠๆฏ้€ฃ็ต"; "action_create" = "ๅปบ็ซ‹"; "action_create_a_room" = "ๅปบ็ซ‹่Šๅคฉๅฎค"; +"action_deactivate" = "Deactivate"; "action_decline" = "ๆ‹’็ต•"; "action_delete_poll" = "ๅˆช้™คๆŠ•็ฅจ"; "action_disable" = "ๅœ็”จ"; @@ -70,6 +73,7 @@ "action_ok" = "OK"; "action_open_settings" = "้–‹ๅ•Ÿ่จญๅฎš"; "action_open_with" = "็”จๅ…ถไป–ๆ–นๅผ้–‹ๅ•Ÿ"; +"action_pin" = "Pin"; "action_quick_reply" = "ๅฟซ้€Ÿๅ›ž่ฆ†"; "action_quote" = "ๅผ•็”จ"; "action_react" = "ๅ›žๆ‡‰"; @@ -80,6 +84,7 @@ "action_report_bug" = "ๅ›žๅ ฑ็จ‹ๅผ้Œฏ่ชค"; "action_report_content" = "ๆชข่ˆ‰ๅ…งๅฎน"; "action_reset" = "้‡่จญ"; +"action_reset_identity" = "Reset identity"; "action_retry" = "ๅ†่ฉฆไธ€ๆฌก"; "action_retry_decryption" = "ๅ†ๆฌกๅ˜—่ฉฆ่งฃๅฏ†"; "action_save" = "ๅ„ฒๅญ˜"; @@ -99,10 +104,18 @@ "action_take_photo" = "ๆ‹็…ง"; "action_tap_for_options" = "้ปžๆ“ŠไปฅๆŸฅ็œ‹้ธ้ …"; "action_try_again" = "ๅ†่ฉฆไธ€ๆฌก"; +"action_unpin" = "Unpin"; +"action_view_in_timeline" = "View in timeline"; "action_view_source" = "ๆชข่ฆ–ๅŽŸๅง‹็ขผ"; "action_yes" = "ๆ˜ฏ"; "action.load_more" = "่ผ‰ๅ…ฅๆ›ดๅคš"; -"action.pin" = "Pin"; +"action_deactivate_account" = "Deactivate account"; +"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" = "Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices."; +"banner.set_up_recovery.title" = "Set up recovery"; "common_about" = "้—œๆ–ผ"; "common_acceptable_use_policy" = "ๅฏๆŽฅๅ—ไฝฟ็”จๆ”ฟ็ญ–"; "common_advanced_settings" = "้€ฒ้šŽ่จญๅฎš"; @@ -214,6 +227,7 @@ "common_waiting_for_decryption_key" = "็ญ‰ๅพ…ๆญคๅ‰‡่จŠๆฏ"; "common.do_not_show_this_again" = "ไธๅ†้กฏ็คบ"; "common.open_source_licenses" = "Open source licenses"; +"common.pinned" = "Pinned"; "common.send_to" = "ๅ‚ณ้€็ตฆ"; "common_no_room_name" = "็„ก่Šๅคฉๅฎคๅ็จฑ"; "common_poll_end_confirmation" = "ๆ‚จ็ขบๅฎš่ฆ็ตๆŸ้€™้ …ๆŠ•็ฅจๅ—Ž๏ผŸ"; @@ -244,6 +258,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_failed_creating_the_permalink" = "็„กๆณ•ๅปบ็ซ‹ๆฐธไน…้€ฃ็ต"; "error_failed_loading_map" = "%1$@็„กๆณ•่ผ‰ๅ…ฅๅœฐๅœ–ใ€‚่ซ‹็จๅพŒๅ†่ฉฆใ€‚"; "error_failed_loading_messages" = "็„กๆณ•่ผ‰ๅ…ฅ่จŠๆฏ"; @@ -254,6 +269,8 @@ "error_some_messages_have_not_been_sent" = "ๆœ‰ไบ›่จŠๆฏๅฐšๆœชๅ‚ณ้€"; "error_unknown" = "Sorry, an error occurred"; "event_shield_reason_authenticity_not_guaranteed" = "The authenticity of this encrypted message can't be guaranteed on this device."; +"event_shield_reason_previously_verified" = "Encrypted by a previously-verified user."; +"event_shield_reason_sent_in_clear" = "Not encrypted."; "event_shield_reason_unknown_device" = "Encrypted by an unknown or deleted device."; "event_shield_reason_unsigned_device" = "Encrypted by a device not verified by its owner."; "event_shield_reason_unverified_identity" = "Encrypted by an unverified user."; @@ -275,11 +292,14 @@ "notification_inline_reply_failed" = "** ็„กๆณ•ๅ‚ณ้€๏ผŒ่ซ‹้–‹ๅ•Ÿ่Šๅคฉๅฎค"; "notification_invitation_action_reject" = "ๆ‹’็ต•"; "notification_invite_body" = "้‚€่ซ‹ๆ‚จ่Šๅคฉ"; +"notification_invite_body_with_sender" = "%1$@ invited you to chat"; "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_sender_me" = "ๆˆ‘"; +"notification_sender_mention_reply" = "%1$@ mentioned or replied"; "notification_test_push_notification_content" = "ๆ‚จๆญฃๅœจๆŸฅ็œ‹้€š็Ÿฅ๏ผ้ปžๆˆ‘๏ผ"; "notification_ticker_text_dm" = "%1$@๏ผš%2$@"; "notification_ticker_text_group" = "%1$@๏ผš%2$@ %3$@"; @@ -312,10 +332,27 @@ "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_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_pinned_timeline_screen_title_empty" = "Pinned messages"; +"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.room.pinned_banner_indicator" = "%1$@ of %2$@"; -"screen.room.pinned_banner_indicator_description" = "%1$@ Pinned messages"; -"screen.room.pinned_banner_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_details_pinned_events_row_title" = "Pinned messages"; +"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_account_provider_change" = "ๆ›ดๆ”นๅธณ่™Ÿๆไพ›่€…"; "screen_account_provider_form_hint" = "ๅฎถไผบๆœๅ™จไฝๅ€"; "screen_account_provider_form_notice" = "่ผธๅ…ฅ้—œ้ตๅญ—ๆˆ–็ถฒๅŸŸๅ็จฑใ€‚"; @@ -398,6 +435,7 @@ "screen_chat_backup_recovery_action_confirm_description" = "Your chat backup is currently out of sync."; "screen_chat_backup_recovery_action_setup" = "Set up recovery"; "screen_chat_backup_recovery_action_setup_description" = "Get access to your encrypted messages if you lose all your devices or are signed out of %1$@ everywhere."; +"screen_create_account_title" = "Create account"; "screen_create_new_recovery_key_list_item_1" = "Open %1$@ in a desktop device"; "screen_create_new_recovery_key_list_item_2" = "Sign into your account again"; "screen_create_new_recovery_key_list_item_3" = "When asked to verify your device, select %1$@"; @@ -421,6 +459,17 @@ "screen_create_room_public_option_description" = "่จŠๆฏๆœชๅŠ ๅฏ†๏ผŒไปปไฝ•ไบบ้ƒฝๅฏไปฅๆŸฅ็œ‹ใ€‚ๆ‚จๅฏไปฅๅœจไน‹ๅพŒๅ•Ÿ็”จๅŠ ๅฏ†ๅŠŸ่ƒฝใ€‚"; "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_edit_poll_delete_confirmation" = "ๆ‚จ็ขบๅฎš่ฆๅˆช้™คๆŠ•็ฅจๅ—Ž๏ผŸ"; "screen_edit_profile_display_name" = "้กฏ็คบๅ็จฑ"; "screen_edit_profile_display_name_placeholder" = "ๆ‚จ็š„้กฏ็คบๅ็จฑ"; @@ -428,12 +477,20 @@ "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" = "Your account details, contacts, preferences, and chat list will be kept"; +"screen_encryption_reset_bullet_2" = "You will lose your existing message history"; +"screen_encryption_reset_bullet_3" = "You will need to verify all your existing devices and contacts again"; +"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_identity_confirmation_create_new_recovery_key" = "ๅปบ็ซ‹ๆ–ฐ็š„ๅพฉๅŽŸ้‡‘้‘ฐ"; "screen_identity_confirmation_subtitle" = "้ฉ—่ญ‰้€™้ƒจ่ฃ็ฝฎไปฅ่จญๅฎšๅฎ‰ๅ…จ้€š่จŠใ€‚"; "screen_identity_confirmation_title" = "็ขบ่ช้€™ๆ˜ฏไฝ ๆœฌไบบ"; +"screen_identity_confirmation_use_another_device" = "ไฝฟ็”จๅฆไธ€้ƒจ่ฃ็ฝฎ"; +"screen_identity_confirmation_use_recovery_key" = "Use recovery key"; "screen_identity_confirmed_subtitle" = "ๆ‚จๅฏไปฅๅฎ‰ๅ…จๅœฐ่ฎ€ๅ–ๅ’Œ็™ผ้€่จŠๆฏไบ†๏ผŒ่ˆ‡ๆ‚จ่Šๅคฉ็š„ไบบไนŸๅฏไปฅไฟกไปป้€™้ƒจ่ฃ็ฝฎใ€‚"; "screen_identity_confirmed_title" = "่ฃ็ฝฎๅทฒ้ฉ—่ญ‰"; -"screen_identity_use_another_device" = "ไฝฟ็”จๅฆไธ€้ƒจ่ฃ็ฝฎ"; "screen_identity_waiting_on_other_device" = "ๆญฃๅœจ็ญ‰ๅพ…ๅ…ถไป–่ฃ็ฝฎ..."; "screen_invites_decline_chat_message" = "Are you sure you want to decline the invitation to join %1$@?"; "screen_invites_decline_chat_title" = "Decline invite"; @@ -556,7 +613,6 @@ "screen_recovery_key_confirm_error_content" = "Please try again to confirm access to your chat backup."; "screen_recovery_key_confirm_error_title" = "Incorrect recovery key"; "screen_recovery_key_confirm_key_description" = "If you have a security key or security phrase, this will work too."; -"screen_recovery_key_confirm_key_label" = "Recovery key or passcode"; "screen_recovery_key_confirm_key_placeholder" = "Enterโ€ฆ"; "screen_recovery_key_confirm_lost_recovery_key" = "Lost your recovery key?"; "screen_recovery_key_confirm_success" = "Recovery key confirmed"; @@ -577,6 +633,14 @@ "screen_report_content_block_user_hint" = "Check if you want to hide all current and future messages from this user"; "screen_report_content_explanation" = "This message will be reported to your homeserverโ€™s administrator. They will not be able to read any encrypted messages."; "screen_report_content_hint" = "ๆชข่ˆ‰้€™ๅ€‹ๅ…งๅฎน็š„ๅŽŸๅ› "; +"screen_reset_encryption_confirmation_alert_action" = "Yes, reset now"; +"screen_reset_encryption_confirmation_alert_subtitle" = "This process is irreversible."; +"screen_reset_encryption_confirmation_alert_title" = "Are you sure you want to reset your identity?"; +"screen_reset_encryption_password_placeholder" = "Enterโ€ฆ"; +"screen_reset_encryption_password_subtitle" = "Confirm that you want to reset your identity."; +"screen_reset_encryption_password_title" = "Enter your account password to continue"; +"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_room_alias_resolver_resolve_alias_failure" = "Failed to resolve room alias."; "screen_room_attachment_source_camera" = "็…ง็›ธๆฉŸ"; "screen_room_attachment_source_camera_video" = "้Œ„ๅฝฑ"; @@ -775,9 +839,6 @@ "screen_signout_save_recovery_key_title" = "Have you saved your recovery key?"; "screen_start_chat_error_starting_chat" = "An error occurred when trying to start a chat"; "screen_view_location_title" = "ไฝ็ฝฎ"; -"screen_waitlist_message" = "There's a high demand for %1$@ on %2$@ at the moment. Come back to the app in a few days and try again.\n\nThanks for your patience!"; -"screen_waitlist_title" = "Youโ€™re almost there."; -"screen_waitlist_title_success" = "You're in."; "screen_welcome_bullet_1" = "้€š่ฉฑใ€ๆŠ•็ฅจใ€ๆœๅฐ‹็ญ‰ๆ›ดๅคšๅŠŸ่ƒฝๅฐ‡ๅœจไปŠๅนด็™ปๅ ดใ€‚"; "screen_welcome_bullet_2" = "ๅœจ้€™ๆฌก็š„ๆ›ดๆ–ฐ๏ผŒๆ‚จ็„กๆณ•ๆŸฅ็œ‹่Šๅคฉๅฎคๅ…ง่ขซๅŠ ๅฏ†็š„ๆญทๅฒ่จŠๆฏใ€‚"; "screen_welcome_bullet_3" = "ๆˆ‘ๅ€‘ๅพˆๆจ‚ๆ„่ฝๅ–ๆ‚จ็š„ๆ„่ฆ‹๏ผŒ่ซ‹ๅˆฐ่จญๅฎš้ ้ขๅ‘Š่จดๆˆ‘ๅ€‘ๆ‚จ็š„ๆƒณๆณ•ใ€‚"; @@ -834,6 +895,12 @@ "state_event_room_name_removed_by_you" = "่Šๅคฉๅฎคๅ็จฑๅทฒ่ขซๆ‚จ็งป้™ค"; "state_event_room_none" = "%1$@ made no changes"; "state_event_room_none_by_you" = "You made no changes"; +"state_event_room_pinned_events_changed" = "%1$@ changed the pinned messages"; +"state_event_room_pinned_events_changed_by_you" = "You changed the pinned messages"; +"state_event_room_pinned_events_pinned" = "%1$@ pinned a message"; +"state_event_room_pinned_events_pinned_by_you" = "You pinned a message"; +"state_event_room_pinned_events_unpinned" = "%1$@ unpinned a message"; +"state_event_room_pinned_events_unpinned_by_you" = "You unpinned a message"; "state_event_room_reject" = "%1$@ ๆ‹’็ต•ไบ†้‚€่ซ‹"; "state_event_room_reject_by_you" = "ๆ‚จๆ‹’็ต•ไบ†้‚€่ซ‹"; "state_event_room_remove" = "%2$@ ๅทฒ่ขซ %1$@ ็งป้™ค"; @@ -921,6 +988,7 @@ "screen_dm_details_unblock_user" = "่งฃ้™คๅฐ้Ž–ไฝฟ็”จ่€…"; "screen_edit_poll_delete_confirmation_title" = "ๅˆช้™คๆŠ•็ฅจ"; "screen_edit_poll_title" = "็ทจ่ผฏๆŠ•็ฅจ"; +"screen_identity_use_another_device" = "ไฝฟ็”จๅฆไธ€้ƒจ่ฃ็ฝฎ"; "screen_login_subtitle" = "Matrix ๆ˜ฏไธ€ๅ€‹้–‹ๆ”พ็ถฒ่ทฏ๏ผŒ็‚บไบ†ๅฎ‰ๅ…จไธ”ๅŽปไธญๅฟƒๅŒ–็š„้€š่จŠ่€Œ็”Ÿใ€‚"; "screen_qr_code_login_invalid_scan_state_retry_button" = "ๅ†่ฉฆไธ€ๆฌก"; "screen_report_content_block_user" = "ๅฐ้Ž–ไฝฟ็”จ่€…"; @@ -945,4 +1013,3 @@ "screen_signout_confirmation_dialog_submit" = "็™ปๅ‡บ"; "screen_signout_confirmation_dialog_title" = "็™ปๅ‡บ"; "screen_signout_preference_item" = "็™ปๅ‡บ"; -"screen_waitlist_message_success" = "ๆญก่ฟŽไฝฟ็”จ %1$@๏ผ"; diff --git a/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.stringsdict index f608783574..f580e973f2 100644 --- a/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.stringsdict @@ -172,6 +172,22 @@ PIN ็ขผ้Œฏ่ชคใ€‚ๆ‚จ้‚„ๆœ‰ %1$d ๆฌกๆฉŸๆœƒ + 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 diff --git a/ElementX/Sources/AppHooks/AppHooks.swift b/ElementX/Sources/AppHooks/AppHooks.swift index b2f7f7106a..fb3bf39b95 100644 --- a/ElementX/Sources/AppHooks/AppHooks.swift +++ b/ElementX/Sources/AppHooks/AppHooks.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/AppHooks/Hooks/AppSettingsHook.swift b/ElementX/Sources/AppHooks/Hooks/AppSettingsHook.swift index 2d886ffff3..f65cbc3a1c 100644 --- a/ElementX/Sources/AppHooks/Hooks/AppSettingsHook.swift +++ b/ElementX/Sources/AppHooks/Hooks/AppSettingsHook.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/AppHooks/Hooks/BugReportHook.swift b/ElementX/Sources/AppHooks/Hooks/BugReportHook.swift index 68b615f735..757c6a7723 100644 --- a/ElementX/Sources/AppHooks/Hooks/BugReportHook.swift +++ b/ElementX/Sources/AppHooks/Hooks/BugReportHook.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/AppHooks/Hooks/CertificateValidatorHook.swift b/ElementX/Sources/AppHooks/Hooks/CertificateValidatorHook.swift index 5103fc3609..4bbe68ea67 100644 --- a/ElementX/Sources/AppHooks/Hooks/CertificateValidatorHook.swift +++ b/ElementX/Sources/AppHooks/Hooks/CertificateValidatorHook.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/AppHooks/Hooks/ClientBuilderHook.swift b/ElementX/Sources/AppHooks/Hooks/ClientBuilderHook.swift index 910f4ae838..c43fc88790 100644 --- a/ElementX/Sources/AppHooks/Hooks/ClientBuilderHook.swift +++ b/ElementX/Sources/AppHooks/Hooks/ClientBuilderHook.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import MatrixRustSDK diff --git a/ElementX/Sources/Application/AppCoordinator.swift b/ElementX/Sources/Application/AppCoordinator.swift index 030b572195..c5b70a1100 100644 --- a/ElementX/Sources/Application/AppCoordinator.swift +++ b/ElementX/Sources/Application/AppCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import AnalyticsEvents @@ -41,7 +32,8 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg private var userSession: UserSessionProtocol? { didSet { userSessionObserver?.cancel() - if userSession != nil { + if let userSession { + userSession.clientProxy.roomsToAwait = storedRoomsToAwait configureElementCallService() configureNotificationManager() observeUserSessionChanges() @@ -66,6 +58,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg private let appRouteURLParser: AppRouteURLParser @Consumable private var storedAppRoute: AppRoute? + private var storedRoomsToAwait: Set = [] init(appDelegate: AppDelegate) { let appHooks = AppHooks() @@ -212,7 +205,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg if let userSessionFlowCoordinator { userSessionFlowCoordinator.handleAppRoute(route, animated: true) } else { - navigationRootCoordinator.setSheetCoordinator(GenericCallLinkCoordinator(parameters: .init(url: url))) + presentCallScreen(genericCallLink: url) } case .userProfile(let userID): if isExternalURL { @@ -312,6 +305,14 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg return } + if content.categoryIdentifier == NotificationConstants.Category.invite { + if let userSession { + userSession.clientProxy.roomsToAwait.insert(roomID) + } else { + storedRoomsToAwait.insert(roomID) + } + } + handleAppRoute(.room(roomID: roomID, via: [])) } @@ -325,10 +326,15 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg guard let roomID = content.userInfo[NotificationConstants.UserInfoKey.roomIdentifier] as? String else { return } - let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) - switch await roomProxy?.timeline.sendMessage(replyText, - html: nil, - intentionalMentions: .empty) { + + 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, + intentionalMentions: .empty) { case .success: break default: @@ -360,20 +366,6 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg MXLog.info("The app was upgraded from \(oldVersion) to \(newVersion)") - if oldVersion < Version(1, 1, 0) { - MXLog.info("Migrating to v1.1.0, signing out the user.") - // Version 1.1.0 switched the Rust crypto store to SQLite - // There are no migrations in place so we need to sign the user out - wipeUserData() - } - - if oldVersion < Version(1, 1, 7) { - MXLog.info("Migrating to v1.1.7, marking accounts as migrated.") - for userID in userSessionStore.userIDs { - appSettings.migratedAccounts[userID] = true - } - } - if oldVersion < Version(1, 6, 0) { MXLog.info("Migrating to v1.6.0, marking identity confirmation onboarding as ran.") if !userSessionStore.userIDs.isEmpty { @@ -414,7 +406,6 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg presentSplashScreen() case (.restoringSession, .createdUserSession, .signedIn): setupUserSession(isNewLogin: false) - case (.signingOut, .signOut, .signingOut): // We can ignore signOut when already in the process of signing out, // such as the SDK sending an authError due to token invalidation. @@ -648,6 +639,33 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg elementCallService.setClientProxy(userSession.clientProxy) } + + private func presentCallScreen(genericCallLink url: URL) { + let configuration = ElementCallConfiguration(genericCallLink: url) + + let callScreenCoordinator = CallScreenCoordinator(parameters: .init(elementCallService: elementCallService, + configuration: configuration, + allowPictureInPicture: false, + appHooks: appHooks)) + + callScreenCoordinator.actions + .sink { [weak self] action in + guard let self else { return } + switch action { + case .pictureInPictureIsAvailable: + break + case .pictureInPictureStarted, .pictureInPictureStopped: + // Don't allow PiP when signed out - the user could login at which point we'd + // need to hand over the call from here to the user session flow coordinator. + MXLog.error("Picture in Picture not supported before login.") + case .dismiss: + navigationRootCoordinator.setOverlayCoordinator(nil) + } + } + .store(in: &cancellables) + + navigationRootCoordinator.setOverlayCoordinator(callScreenCoordinator, animated: false) + } private func configureNotificationManager() { notificationManager.setUserSession(userSession) diff --git a/ElementX/Sources/Application/AppCoordinatorProtocol.swift b/ElementX/Sources/Application/AppCoordinatorProtocol.swift index 7ac7d1d682..6142a8b354 100644 --- a/ElementX/Sources/Application/AppCoordinatorProtocol.swift +++ b/ElementX/Sources/Application/AppCoordinatorProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Application/AppCoordinatorStateMachine.swift b/ElementX/Sources/Application/AppCoordinatorStateMachine.swift index f4806073da..2ed008daf9 100644 --- a/ElementX/Sources/Application/AppCoordinatorStateMachine.swift +++ b/ElementX/Sources/Application/AppCoordinatorStateMachine.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Application/AppDelegate.swift b/ElementX/Sources/Application/AppDelegate.swift index 628067204e..ab013609fc 100644 --- a/ElementX/Sources/Application/AppDelegate.swift +++ b/ElementX/Sources/Application/AppDelegate.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Application/AppMediator.swift b/ElementX/Sources/Application/AppMediator.swift index 8192976e55..12bb8f74e3 100644 --- a/ElementX/Sources/Application/AppMediator.swift +++ b/ElementX/Sources/Application/AppMediator.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import AVFoundation diff --git a/ElementX/Sources/Application/AppMediatorProtocol.swift b/ElementX/Sources/Application/AppMediatorProtocol.swift index fd3364f4fa..d7043f2983 100644 --- a/ElementX/Sources/Application/AppMediatorProtocol.swift +++ b/ElementX/Sources/Application/AppMediatorProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Application/AppSettings.swift b/ElementX/Sources/Application/AppSettings.swift index 2f10ec48f5..556c88374a 100644 --- a/ElementX/Sources/Application/AppSettings.swift +++ b/ElementX/Sources/Application/AppSettings.swift @@ -1,29 +1,25 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation import SwiftUI +// Common settings between app and NSE +protocol CommonSettingsProtocol { + var logLevel: TracingConfiguration.LogLevel { get } + var invisibleCryptoEnabled: Bool { get } +} + /// Store Element specific app settings. final class AppSettings { private enum UserDefaultsKeys: String { case lastVersionLaunched case appLockNumberOfPINAttempts case appLockNumberOfBiometricAttempts - case migratedAccounts case timelineStyle case analyticsConsentState @@ -43,11 +39,11 @@ final class AppSettings { case elementCallEncryptionEnabled // Feature flags - case simplifiedSlidingSyncEnabled + case slidingSyncDiscovery case publicSearchEnabled case fuzzyRoomListSearchEnabled case pinningEnabled - case timelineItemAuthenticityEnabled + case invisibleCryptoEnabled } private static var suiteName: String = InfoPlistReader.main.appGroupIdentifier @@ -108,10 +104,6 @@ final class AppSettings { // Tchap: define Tchap DEV default HomeServer // private(set) var defaultHomeserverAddress = "matrix.org" private(set) var defaultHomeserverAddress = "matrix.dev01.tchap.incubateur.net" - - /// An override of the homeserver's Sliding Sync proxy URL. This allows development against servers - /// that don't yet have an officially trusted proxy configured in their well-known. - let slidingSyncProxyURL: URL? = nil /// The task identifier used for background app refresh. Also used in main target's the Info.plist let backgroundAppRefreshTaskIdentifier = "io.element.elementx.background.refresh" @@ -175,14 +167,10 @@ final class AppSettings { contacts: [supportEmailAddress], staticRegistrations: oidcStaticRegistrations.mapKeys { $0.absoluteString }, dynamicRegistrationsFile: .sessionsBaseDirectory.appending(path: "oidc/registrations.json")) - - /// A dictionary of accounts that have performed an initial sync through their proxy. - /// - /// This is a temporary workaround. In the future we should be able to receive a signal from the - /// proxy that it is the first sync (or that an upgrade on the backend will involve a slower sync). - @UserPreference(key: UserDefaultsKeys.migratedAccounts, defaultValue: [:], storageType: .userDefaults(store)) - var migratedAccounts: [String: Bool] - + + /// A temporary hack to allow registration on matrix.org until MAS is deployed. + let webRegistrationEnabled = true + // MARK: - Notifications var pusherAppId: String { @@ -285,12 +273,13 @@ final class AppSettings { @UserPreference(key: UserDefaultsKeys.fuzzyRoomListSearchEnabled, defaultValue: false, storageType: .userDefaults(store)) var fuzzyRoomListSearchEnabled - @UserPreference(key: UserDefaultsKeys.pinningEnabled, defaultValue: false, storageType: .userDefaults(store)) + @UserPreference(key: UserDefaultsKeys.pinningEnabled, defaultValue: true, storageType: .userDefaults(store)) var pinningEnabled - @UserPreference(key: UserDefaultsKeys.timelineItemAuthenticityEnabled, defaultValue: false, storageType: .userDefaults(store)) - var timelineItemAuthenticityEnabled - + enum SlidingSyncDiscovery: Codable { case proxy, native, forceNative } + @UserPreference(key: UserDefaultsKeys.slidingSyncDiscovery, defaultValue: .native, storageType: .userDefaults(store)) + var slidingSyncDiscovery: SlidingSyncDiscovery + #endif // MARK: - Shared @@ -298,8 +287,9 @@ final class AppSettings { @UserPreference(key: UserDefaultsKeys.logLevel, defaultValue: TracingConfiguration.LogLevel.info, storageType: .userDefaults(store)) var logLevel - // MARK: Shared Feature Flags - - @UserPreference(key: UserDefaultsKeys.simplifiedSlidingSyncEnabled, defaultValue: false, storageType: .userDefaults(store)) - var simplifiedSlidingSyncEnabled + /// Configuration to enable invisible crypto. In this mode only devices signed by their owner will be considered in e2ee rooms. + @UserPreference(key: UserDefaultsKeys.invisibleCryptoEnabled, defaultValue: false, storageType: .userDefaults(store)) + var invisibleCryptoEnabled } + +extension AppSettings: CommonSettingsProtocol { } diff --git a/ElementX/Sources/Application/Application.swift b/ElementX/Sources/Application/Application.swift index efef47f745..ad1f9823fe 100644 --- a/ElementX/Sources/Application/Application.swift +++ b/ElementX/Sources/Application/Application.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Application/CoordinatorProtocol.swift b/ElementX/Sources/Application/CoordinatorProtocol.swift index 88b4bd769f..e0e3996c49 100644 --- a/ElementX/Sources/Application/CoordinatorProtocol.swift +++ b/ElementX/Sources/Application/CoordinatorProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Application/FlowCoordinatorProtocol.swift b/ElementX/Sources/Application/FlowCoordinatorProtocol.swift index aae3342464..e89f186ef2 100644 --- a/ElementX/Sources/Application/FlowCoordinatorProtocol.swift +++ b/ElementX/Sources/Application/FlowCoordinatorProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Application/Navigation/AppRoutes.swift b/ElementX/Sources/Application/Navigation/AppRoutes.swift index 2e6aec080b..507e77b4b9 100644 --- a/ElementX/Sources/Application/Navigation/AppRoutes.swift +++ b/ElementX/Sources/Application/Navigation/AppRoutes.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Application/Navigation/NavigationCoordinators.swift b/ElementX/Sources/Application/Navigation/NavigationCoordinators.swift index 3ba5cf885c..7441c85dfb 100644 --- a/ElementX/Sources/Application/Navigation/NavigationCoordinators.swift +++ b/ElementX/Sources/Application/Navigation/NavigationCoordinators.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -115,6 +106,28 @@ class NavigationSplitCoordinator: CoordinatorProtocol, ObservableObject, CustomS fullScreenCoverModule?.coordinator } + @Published fileprivate var overlayModule: NavigationModule? { + didSet { + if let oldValue { + logPresentationChange("Remove overlay", oldValue) + oldValue.tearDown() + } + + if let overlayModule { + logPresentationChange("Set overlay", overlayModule) + overlayModule.coordinator?.start() + } + } + } + + /// The currently displayed overlay coordinator + var overlayCoordinator: (any CoordinatorProtocol)? { + overlayModule?.coordinator + } + + enum OverlayPresentationMode { case fullScreen, minimized } + @Published fileprivate var overlayPresentationMode: OverlayPresentationMode = .minimized + fileprivate var compactLayoutRootModule: NavigationModule? { if let sidebarNavigationStackCoordinator = sidebarModule?.coordinator as? NavigationStackCoordinator { if let sidebarRootModule = sidebarNavigationStackCoordinator.rootModule { @@ -282,6 +295,47 @@ class NavigationSplitCoordinator: CoordinatorProtocol, ObservableObject, CustomS fullScreenCoverModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback) } } + + /// Present an overlay on top of the split view + /// - Parameters: + /// - coordinator: the coordinator to display + /// - presentationMode: how the coordinator should be presented + /// - animated: whether the transition should be animated + /// - dismissalCallback: called when the overlay has been dismissed, programatically or otherwise + func setOverlayCoordinator(_ coordinator: (any CoordinatorProtocol)?, + presentationMode: OverlayPresentationMode = .fullScreen, + animated: Bool = true, + dismissalCallback: (() -> Void)? = nil) { + guard let coordinator else { + overlayModule = nil + return + } + + if overlayModule?.coordinator === coordinator { + fatalError("Cannot use the same coordinator more than once") + } + + var transaction = Transaction() + transaction.disablesAnimations = !animated + + withTransaction(transaction) { + overlayPresentationMode = presentationMode + overlayModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback) + } + } + + /// Updates the presentation of the overlay coordinator. + /// - Parameters: + /// - mode: The type of presentation to use. + /// - animated: whether the transition should be animated + func setOverlayPresentationMode(_ mode: OverlayPresentationMode, animated: Bool = true) { + var transaction = Transaction() + transaction.disablesAnimations = !animated + + withTransaction(transaction) { + overlayPresentationMode = mode + } + } // MARK: - CoordinatorProtocol @@ -385,6 +439,17 @@ private struct NavigationSplitCoordinatorView: View { module.coordinator?.toPresentable() .id(module.id) } + .overlay { + Group { + if let coordinator = navigationSplitCoordinator.overlayModule?.coordinator { + coordinator.toPresentable() + .opacity(navigationSplitCoordinator.overlayPresentationMode == .minimized ? 0 : 1) + .transition(.opacity) + } + } + .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) { value in diff --git a/ElementX/Sources/Application/Navigation/NavigationModule.swift b/ElementX/Sources/Application/Navigation/NavigationModule.swift index 247bcfe202..15e1fb9732 100644 --- a/ElementX/Sources/Application/Navigation/NavigationModule.swift +++ b/ElementX/Sources/Application/Navigation/NavigationModule.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Application/Navigation/NavigationRootCoordinator.swift b/ElementX/Sources/Application/Navigation/NavigationRootCoordinator.swift index 682f3c8788..ed14d15108 100644 --- a/ElementX/Sources/Application/Navigation/NavigationRootCoordinator.swift +++ b/ElementX/Sources/Application/Navigation/NavigationRootCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -56,6 +47,25 @@ class NavigationRootCoordinator: ObservableObject, CoordinatorProtocol, CustomSt sheetModule?.coordinator } + @Published fileprivate var overlayModule: NavigationModule? { + didSet { + if let oldValue { + logPresentationChange("Remove overlay", oldValue) + oldValue.tearDown() + } + + if let overlayModule { + logPresentationChange("Set overlay", overlayModule) + overlayModule.coordinator?.start() + } + } + } + + /// The currently displayed overlay coordinator + var overlayCoordinator: (any CoordinatorProtocol)? { + overlayModule?.coordinator + } + /// Sets or replaces the presented coordinator /// - Parameter coordinator: the coordinator to display func setRootCoordinator(_ coordinator: (any CoordinatorProtocol)?, animated: Bool = true, dismissalCallback: (() -> Void)? = nil) { @@ -90,6 +100,31 @@ class NavigationRootCoordinator: ObservableObject, CoordinatorProtocol, CustomSt sheetModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback) } } + + /// Present an overlay on top of the split view + /// - Parameters: + /// - coordinator: the coordinator to display + /// - animated: whether the transition should be animated + /// - dismissalCallback: called when the overlay has been dismissed, programatically or otherwise + func setOverlayCoordinator(_ coordinator: (any CoordinatorProtocol)?, + animated: Bool = true, + dismissalCallback: (() -> Void)? = nil) { + guard let coordinator else { + overlayModule = nil + return + } + + if overlayModule?.coordinator === coordinator { + fatalError("Cannot use the same coordinator more than once") + } + + var transaction = Transaction() + transaction.disablesAnimations = !animated + + withTransaction(transaction) { + overlayModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback) + } + } // MARK: - CoordinatorProtocol @@ -127,5 +162,14 @@ private struct NavigationRootCoordinatorView: View { .sheet(item: $rootCoordinator.sheetModule) { module in module.coordinator?.toPresentable() } + .overlay { + Group { + if let coordinator = rootCoordinator.overlayModule?.coordinator { + coordinator.toPresentable() + .transition(.opacity) + } + } + .animation(.elementDefault, value: rootCoordinator.overlayModule) + } } } diff --git a/ElementX/Sources/Application/ServiceLocator.swift b/ElementX/Sources/Application/ServiceLocator.swift index 7b2cb355ad..0e52db7e20 100644 --- a/ElementX/Sources/Application/ServiceLocator.swift +++ b/ElementX/Sources/Application/ServiceLocator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Application/Windowing/OrientationManagerProtocol.swift b/ElementX/Sources/Application/Windowing/OrientationManagerProtocol.swift index 7112149d63..65964d8019 100644 --- a/ElementX/Sources/Application/Windowing/OrientationManagerProtocol.swift +++ b/ElementX/Sources/Application/Windowing/OrientationManagerProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Application/Windowing/SceneDelegate.swift b/ElementX/Sources/Application/Windowing/SceneDelegate.swift index b5e5bf3318..ddb1486840 100644 --- a/ElementX/Sources/Application/Windowing/SceneDelegate.swift +++ b/ElementX/Sources/Application/Windowing/SceneDelegate.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Application/Windowing/WindowManager.swift b/ElementX/Sources/Application/Windowing/WindowManager.swift index 884128d2ec..3b62b58cb3 100644 --- a/ElementX/Sources/Application/Windowing/WindowManager.swift +++ b/ElementX/Sources/Application/Windowing/WindowManager.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Application/Windowing/WindowManagerProtocol.swift b/ElementX/Sources/Application/Windowing/WindowManagerProtocol.swift index eef5d573ab..22d76c699d 100644 --- a/ElementX/Sources/Application/Windowing/WindowManagerProtocol.swift +++ b/ElementX/Sources/Application/Windowing/WindowManagerProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/FlowCoordinators/AppLockFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/AppLockFlowCoordinator.swift index 2ed89462cb..322cecf830 100644 --- a/ElementX/Sources/FlowCoordinators/AppLockFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/AppLockFlowCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -150,7 +141,6 @@ class AppLockFlowCoordinator: CoordinatorProtocol { switch (fromState, event) { case (.initial, .start): return .backgrounded - case (.unlocked, .willResignActive): return .appObscured case (.appObscured, .didBecomeActive): @@ -174,14 +164,12 @@ class AppLockFlowCoordinator: CoordinatorProtocol { return .unlocked case (.attemptingPINUnlock, .forceLogout): return .loggingOut - // Transition to a valid state when enabling the service for the first time. case (.initial, .serviceEnabled): return .unlocked // Transition to a valid state once the service is disabled following a forced logout. case (.loggingOut, .serviceDisabled): return .unlocked - default: return fromState } diff --git a/ElementX/Sources/FlowCoordinators/AppLockSetupFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/AppLockSetupFlowCoordinator.swift index 78bcbdd1fb..203e899621 100644 --- a/ElementX/Sources/FlowCoordinators/AppLockSetupFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/AppLockSetupFlowCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/FlowCoordinators/AuthenticationFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/AuthenticationFlowCoordinator.swift index 01b28d5963..996ce5b743 100644 --- a/ElementX/Sources/FlowCoordinators/AuthenticationFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/AuthenticationFlowCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -86,7 +77,8 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { // MARK: - Private private func showStartScreen() { - let coordinator = AuthenticationStartScreenCoordinator() + let parameters = AuthenticationStartScreenParameters(webRegistrationEnabled: appSettings.webRegistrationEnabled) + let coordinator = AuthenticationStartScreenCoordinator(parameters: parameters) coordinator.actions .sink { [weak self] action in @@ -94,9 +86,11 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { switch action { case .loginManually: - Task { await self.startAuthentication() } + Task { await self.startAuthentication(flow: .login) } case .loginWithQR: startQRCodeLogin() + case .register: + Task { await self.startAuthentication(flow: .register) } case .reportProblem: showReportProblemScreen() } @@ -119,7 +113,7 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { switch action { case .signInManually: navigationStackCoordinator.setSheetCoordinator(nil) - Task { await self.startAuthentication() } + Task { await self.startAuthentication(flow: .login) } case .cancel: navigationStackCoordinator.setSheetCoordinator(nil) case .done(let userSession): @@ -143,20 +137,20 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { bugReportFlowCoordinator?.start() } - private func startAuthentication() async { + private func startAuthentication(flow: AuthenticationFlow) async { startLoading() switch await authenticationService.configure(for: appSettings.defaultHomeserverAddress) { case .success: stopLoading() - showServerConfirmationScreen() + showServerConfirmationScreen(authenticationFlow: flow) case .failure: stopLoading() - showServerSelectionScreen(isModallyPresented: false) + showServerSelectionScreen(authenticationFlow: flow, isModallyPresented: false) } } - private func showServerSelectionScreen(isModallyPresented: Bool) { + private func showServerSelectionScreen(authenticationFlow: AuthenticationFlow, isModallyPresented: Bool) { let navigationCoordinator = NavigationStackCoordinator() let parameters = ServerSelectionScreenCoordinatorParameters(authenticationService: authenticationService, @@ -175,13 +169,18 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { } else { // We are here because the default server failed to respond. if authenticationService.homeserver.value.loginMode == .password { - // Add the password login screen directly to the flow, its fine. - showLoginScreen() + if authenticationFlow == .login { + // Add the password login screen directly to the flow, its fine. + showLoginScreen() + } else { + // Add the web registration screen directly to the flow, its fine. + showWebRegistration() + } } else { // OIDC is presented from the confirmation screen so replace the // server selection screen which was inserted to handle the failure. navigationStackCoordinator.pop() - showServerConfirmationScreen() + showServerConfirmationScreen(authenticationFlow: authenticationFlow) } } case .dismiss: @@ -198,9 +197,9 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { } } - private func showServerConfirmationScreen() { + private func showServerConfirmationScreen(authenticationFlow: AuthenticationFlow) { let parameters = ServerConfirmationScreenCoordinatorParameters(authenticationService: authenticationService, - authenticationFlow: .login) + authenticationFlow: authenticationFlow) let coordinator = ServerConfirmationScreenCoordinator(parameters: parameters) coordinator.actions.sink { [weak self] action in @@ -210,11 +209,13 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { case .continue(let window): if authenticationService.homeserver.value.loginMode == .oidc, let window { showOIDCAuthentication(presentationAnchor: window) + } else if authenticationFlow == .register { + showWebRegistration() } else { showLoginScreen() } case .changeServer: - showServerSelectionScreen(isModallyPresented: true) + showServerSelectionScreen(authenticationFlow: authenticationFlow, isModallyPresented: true) } } .store(in: &cancellables) @@ -222,6 +223,26 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { navigationStackCoordinator.push(coordinator) } + private func showWebRegistration() { + let parameters = WebRegistrationScreenCoordinatorParameters(authenticationService: authenticationService, + userIndicatorController: userIndicatorController) + let coordinator = WebRegistrationScreenCoordinator(parameters: parameters) + + coordinator.actionsPublisher.sink { [weak self] action in + guard let self else { return } + + switch action { + case .cancel: + navigationStackCoordinator.setSheetCoordinator(nil) + case .signedIn(let userSession): + userHasSignedIn(userSession: userSession) + } + } + .store(in: &cancellables) + + navigationStackCoordinator.setSheetCoordinator(coordinator) + } + private func showOIDCAuthentication(presentationAnchor: UIWindow) { startLoading() @@ -264,34 +285,13 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { case .configuredForOIDC: // Pop back to the confirmation screen for OIDC login to continue. navigationStackCoordinator.pop(animated: false) - case .isOnWaitlist(let credentials): - showWaitlistScreen(for: credentials) } } .store(in: &cancellables) navigationStackCoordinator.push(coordinator) } - - private func showWaitlistScreen(for credentials: WaitlistScreenCredentials) { - let parameters = WaitlistScreenCoordinatorParameters(credentials: credentials, - authenticationService: authenticationService) - let coordinator = WaitlistScreenCoordinator(parameters: parameters) - - coordinator.actions.sink { [weak self] action in - guard let self else { return } - switch action { - case .signedIn(let userSession): - userHasSignedIn(userSession: userSession) - case .cancel: - navigationStackCoordinator.pop() - } - } - .store(in: &cancellables) - navigationStackCoordinator.push(coordinator) - } - private func userHasSignedIn(userSession: UserSessionProtocol) { delegate?.authenticationFlowCoordinator(didLoginWithSession: userSession) } diff --git a/ElementX/Sources/FlowCoordinators/BugReportFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/BugReportFlowCoordinator.swift index e5a7f9ab4f..04a37713d5 100644 --- a/ElementX/Sources/FlowCoordinators/BugReportFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/BugReportFlowCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/FlowCoordinators/OnboardingFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/OnboardingFlowCoordinator.swift index fb5c0ec26a..ff1b48e11a 100644 --- a/ElementX/Sources/FlowCoordinators/OnboardingFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/OnboardingFlowCoordinator.swift @@ -1,23 +1,18 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine import Foundation import SwiftState +enum OnboardingFlowCoordinatorAction { + case logout +} + class OnboardingFlowCoordinator: FlowCoordinatorProtocol { private let userSession: UserSessionProtocol private let appLockService: AppLockServiceProtocol @@ -52,6 +47,13 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol { // periphery: ignore - used to store the coordinator to avoid deallocation private var appLockFlowCoordinator: AppLockSetupFlowCoordinator? + private let actionsSubject: PassthroughSubject = .init() + var actions: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + private var verificationStateCancellable: AnyCancellable? + init(userSession: UserSessionProtocol, appLockService: AppLockServiceProtocol, analyticsService: AnalyticsService, @@ -74,6 +76,24 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol { self.navigationStackCoordinator = NavigationStackCoordinator() stateMachine = .init(state: .initial) + + // Verification can change as part of the onboarding flow by verifying with + // another device, using a recovery key or by resetting one's crypto identity. + // It can also happen that onboarding started before it had a chance to update, + // usually seen when registering a new account. + // Handle all those cases here instead of spreading them throughout the code. + verificationStateCancellable = userSession.sessionSecurityStatePublisher + .map(\.verificationState) + .removeDuplicates() + .sink { [weak self] value in + guard let self, + value == .verified, + stateMachine.state == .identityConfirmation else { return } + + appSettings.hasRunIdentityConfirmationOnboarding = true + stateMachine.tryEvent(.nextSkippingIdentityConfimed) + self.verificationStateCancellable = nil + } } var shouldStart: Bool { @@ -140,7 +160,6 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol { return .notificationPermissions case (.initial, false, false, false, false): return .finished - case (.identityConfirmation, _, _, _, _): if event == .nextSkippingIdentityConfimed { // Used when the verification state has updated to verified @@ -166,22 +185,18 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol { return .notificationPermissions case (.identityConfirmed, _, false, false, false): return .finished - case (.appLockSetup, _, _, true, _): return .analyticsPrompt case (.appLockSetup, _, _, false, true): return .notificationPermissions case (.appLockSetup, _, _, false, false): return .finished - case (.analyticsPrompt, _, _, _, true): return .notificationPermissions case (.analyticsPrompt, _, _, _, false): return .finished - case (.notificationPermissions, _, _, _, _): return .finished - default: return nil } @@ -234,33 +249,13 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol { stateMachine.tryEvent(.nextSkippingIdentityConfimed) case .reset: presentEncryptionResetScreen() + case .logout: + actionsSubject.send(.logout) } } .store(in: &cancellables) - // If the verification state is still unknown wait for it to resolve - // and just move on to the next steps if verified - var verificationStateCancellable: AnyCancellable? - if userSession.sessionSecurityStatePublisher.value.verificationState == .unknown { - verificationStateCancellable = userSession.sessionSecurityStatePublisher - .map(\.verificationState) - .removeDuplicates() - .sink { [weak self] value in - guard let self else { return } - - if value == .verified { - appSettings.hasRunIdentityConfirmationOnboarding = true - stateMachine.tryEvent(.nextSkippingIdentityConfimed) - } else { - // Captured by the block below, nil-ing it wouldn't work - verificationStateCancellable?.cancel() - } - } - } - - presentCoordinator(coordinator) { [verificationStateCancellable] in - verificationStateCancellable?.cancel() - } + presentCoordinator(coordinator) } private func presentSessionVerificationScreen() async { @@ -273,13 +268,10 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol { let coordinator = SessionVerificationScreenCoordinator(parameters: parameters) coordinator.actions - .sink { [weak self] action in - guard let self else { return } - + .sink { action in switch action { case .done: - appSettings.hasRunIdentityConfirmationOnboarding = true - stateMachine.tryEvent(.next) + break // Moving to next state is handled by the global session verification listener } } .store(in: &cancellables) @@ -300,8 +292,7 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol { switch action { case .recoveryFixed: - appSettings.hasRunIdentityConfirmationOnboarding = true - stateMachine.tryEvent(.next) + break // Moving to next state is Handled by the global session verification listener case .resetEncryption: presentEncryptionResetScreen() default: @@ -329,8 +320,7 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol { case .requestOIDCAuthorisation(let url): presentOIDCAuthorisationScreen(url: url) case .resetFinished: - appSettings.hasRunIdentityConfirmationOnboarding = true - stateMachine.tryEvent(.next) + // Moving to next state is handled by the global session verification listener navigationStackCoordinator.setSheetCoordinator(nil) } } diff --git a/ElementX/Sources/FlowCoordinators/PinnedEventsTimelineFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/PinnedEventsTimelineFlowCoordinator.swift new file mode 100644 index 0000000000..fd021d3cbb --- /dev/null +++ b/ElementX/Sources/FlowCoordinators/PinnedEventsTimelineFlowCoordinator.swift @@ -0,0 +1,152 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Combine +import Foundation + +enum PinnedEventsTimelineFlowCoordinatorAction { + case finished + case displayUser(userID: String) + case forwardedMessageToRoom(roomID: String) + case displayRoomScreenWithFocussedPin(eventID: String) +} + +class PinnedEventsTimelineFlowCoordinator: FlowCoordinatorProtocol { + private let navigationStackCoordinator: NavigationStackCoordinator + private let userSession: UserSessionProtocol + private let roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol + private let roomProxy: JoinedRoomProxyProtocol + private let userIndicatorController: UserIndicatorControllerProtocol + private let appMediator: AppMediatorProtocol + + private let actionsSubject: PassthroughSubject = .init() + var actionsPublisher: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + private var cancellables = Set() + + init(navigationStackCoordinator: NavigationStackCoordinator, + userSession: UserSessionProtocol, + roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol, + roomProxy: JoinedRoomProxyProtocol, + userIndicatorController: UserIndicatorControllerProtocol, + appMediator: AppMediatorProtocol) { + self.navigationStackCoordinator = navigationStackCoordinator + self.userSession = userSession + self.roomTimelineControllerFactory = roomTimelineControllerFactory + self.roomProxy = roomProxy + self.userIndicatorController = userIndicatorController + self.appMediator = appMediator + } + + func start() { + Task { await presentPinnedEventsTimeline() } + } + + func handleAppRoute(_ appRoute: AppRoute, animated: Bool) { + fatalError() + } + + func clearRoute(animated: Bool) { + fatalError() + } + + private func presentPinnedEventsTimeline() async { + let userID = userSession.clientProxy.userID + let timelineItemFactory = RoomTimelineItemFactory(userID: userID, + attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), + stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID)) + + guard let timelineController = await roomTimelineControllerFactory.buildRoomPinnedTimelineController(roomProxy: roomProxy, timelineItemFactory: timelineItemFactory) else { + fatalError("This can never fail because we allow this view to be presented only when the timeline is fully loaded and not nil") + } + + let coordinator = PinnedEventsTimelineScreenCoordinator(parameters: .init(roomProxy: roomProxy, + timelineController: timelineController, + mediaProvider: userSession.mediaProvider, + mediaPlayerProvider: MediaPlayerProvider(), + voiceMessageMediaManager: userSession.voiceMessageMediaManager, + appMediator: appMediator)) + + coordinator.actions + .sink { [weak self] action in + guard let self else { return } + + switch action { + case .dismiss: + actionsSubject.send(.finished) + case .displayUser(let userID): + actionsSubject.send(.displayUser(userID: userID)) + case .presentLocationViewer(let geoURI, let description): + presentMapNavigator(geoURI: geoURI, description: description) + case .displayMessageForwarding(let forwardingItem): + presentMessageForwarding(with: forwardingItem) + case .displayRoomScreenWithFocussedPin(let eventID): + actionsSubject.send(.displayRoomScreenWithFocussedPin(eventID: eventID)) + } + } + .store(in: &cancellables) + + navigationStackCoordinator.setRootCoordinator(coordinator) + } + + private func presentMapNavigator(geoURI: GeoURI, description: String?) { + let stackCoordinator = NavigationStackCoordinator() + + let params = StaticLocationScreenCoordinatorParameters(interactionMode: .viewOnly(geoURI: geoURI, description: description), appMediator: appMediator) + let coordinator = StaticLocationScreenCoordinator(parameters: params) + + coordinator.actions.sink { [weak self] action in + guard let self else { return } + switch action { + case .selectedLocation: + // We don't handle the sending/picker case in this flow + break + case .close: + self.navigationStackCoordinator.setSheetCoordinator(nil) + } + } + .store(in: &cancellables) + + stackCoordinator.setRootCoordinator(coordinator) + + navigationStackCoordinator.setSheetCoordinator(stackCoordinator) + } + + private func presentMessageForwarding(with forwardingItem: MessageForwardingItem) { + guard let roomSummaryProvider = userSession.clientProxy.alternateRoomSummaryProvider else { + fatalError() + } + + let stackCoordinator = NavigationStackCoordinator() + + let parameters = MessageForwardingScreenCoordinatorParameters(forwardingItem: forwardingItem, + clientProxy: userSession.clientProxy, + roomSummaryProvider: roomSummaryProvider, + mediaProvider: userSession.mediaProvider, + userIndicatorController: userIndicatorController) + let coordinator = MessageForwardingScreenCoordinator(parameters: parameters) + + coordinator.actions.sink { [weak self] action in + guard let self else { return } + + switch action { + case .dismiss: + navigationStackCoordinator.setSheetCoordinator(nil) + case .sent(let roomID): + navigationStackCoordinator.setSheetCoordinator(nil) + actionsSubject.send(.forwardedMessageToRoom(roomID: roomID)) + } + } + .store(in: &cancellables) + + stackCoordinator.setRootCoordinator(coordinator) + + navigationStackCoordinator.setSheetCoordinator(stackCoordinator) + } +} diff --git a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift index bbd3d67eb2..76a1d7cb52 100644 --- a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -20,7 +11,7 @@ import SwiftUI import UserNotifications enum RoomFlowCoordinatorAction: Equatable { - case presentCallScreen(roomProxy: RoomProxyProtocol) + case presentCallScreen(roomProxy: JoinedRoomProxyProtocol) case finished static func == (lhs: RoomFlowCoordinatorAction, rhs: RoomFlowCoordinatorAction) -> Bool { @@ -58,12 +49,13 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { private let roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol private let navigationStackCoordinator: NavigationStackCoordinator private let emojiProvider: EmojiProviderProtocol + private let ongoingCallRoomIDPublisher: CurrentValuePublisher private let appMediator: AppMediatorProtocol private let appSettings: AppSettings private let analytics: AnalyticsService private let userIndicatorController: UserIndicatorControllerProtocol - private var roomProxy: RoomProxyProtocol! + private var roomProxy: JoinedRoomProxyProtocol! private var roomScreenCoordinator: RoomScreenCoordinator? private weak var joinRoomScreenCoordinator: JoinRoomScreenCoordinator? @@ -71,6 +63,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { // periphery:ignore - used to avoid deallocation private var rolesAndPermissionsFlowCoordinator: RoomRolesAndPermissionsFlowCoordinator? // periphery:ignore - used to avoid deallocation + private var pinnedEventsTimelineFlowCoordinator: PinnedEventsTimelineFlowCoordinator? + // periphery:ignore - used to avoid deallocation private var childRoomFlowCoordinator: RoomFlowCoordinator? private let stateMachine: StateMachine = .init(state: .initial) @@ -90,6 +84,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol, navigationStackCoordinator: NavigationStackCoordinator, emojiProvider: EmojiProviderProtocol, + ongoingCallRoomIDPublisher: CurrentValuePublisher, appMediator: AppMediatorProtocol, appSettings: AppSettings, analytics: AnalyticsService, @@ -100,6 +95,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { self.roomTimelineControllerFactory = roomTimelineControllerFactory self.navigationStackCoordinator = navigationStackCoordinator self.emojiProvider = emojiProvider + self.ongoingCallRoomIDPublisher = ongoingCallRoomIDPublisher self.appMediator = appMediator self.appSettings = appSettings self.analytics = analytics @@ -139,7 +135,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { Task { if roomProxy == nil { - guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) else { + guard case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomID) else { return } @@ -163,7 +159,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { } else if roomID != roomProxy.id { stateMachine.tryEvent(.startChildFlow(roomID: roomID, via: via, entryPoint: .eventID(eventID)), userInfo: EventUserInfo(animated: animated)) } else { - roomScreenCoordinator?.focusOnEvent(eventID: eventID) + roomScreenCoordinator?.focusOnEvent(.init(eventID: eventID, shouldSetPin: false)) } case .roomAlias, .childRoomAlias, .eventOnRoomAlias, .childEventOnRoomAlias: break // These are converted to a room ID route one level above. @@ -173,7 +169,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { } private func presentCallScreen(roomID: String) async { - guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) else { + guard case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomID) else { return } @@ -183,15 +179,16 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { private func handleRoomRoute(roomID: String, via: [String], focussedEventID: String? = nil, animated: Bool) async { guard roomID == self.roomID else { fatalError("Navigation route doesn't belong to this room flow.") } - guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) else { + guard let room = await userSession.clientProxy.roomForIdentifier(roomID) else { stateMachine.tryEvent(.presentJoinRoomScreen(via: via), userInfo: EventUserInfo(animated: animated)) return } - switch roomProxy.membership { - case .joined: + switch room { + case .joined(let roomProxy): await storeAndSubscribeToRoomProxy(roomProxy) - stateMachine.tryEvent(.presentRoom(focussedEventID: focussedEventID), userInfo: EventUserInfo(animated: animated)) + let focussedEvent = focussedEventID.map { FocusEvent(eventID: $0, shouldSetPin: false) } + stateMachine.tryEvent(.presentRoom(focussedEvent: focussedEvent), userInfo: EventUserInfo(animated: animated)) default: stateMachine.tryEvent(.presentJoinRoomScreen(via: via), userInfo: EventUserInfo(animated: animated)) } @@ -207,7 +204,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { // MARK: - Private - private func storeAndSubscribeToRoomProxy(_ roomProxy: RoomProxyProtocol) async { + private func storeAndSubscribeToRoomProxy(_ roomProxy: JoinedRoomProxyProtocol) async { if let oldRoomProxy = self.roomProxy { if oldRoomProxy.id != roomProxy.id { fatalError("Trying to create different room proxies for the same flow coordinator") @@ -216,11 +213,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { MXLog.warning("Found an existing proxy, returning.") return } - - guard roomProxy.membership == .joined else { - fatalError("Requesting room details for an unjoined room") - } - + await roomProxy.subscribeForUpdates() // Make sure not to set this until after the subscription has succeeded, otherwise the @@ -237,95 +230,78 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { return .joinRoomScreen case (_, .dismissJoinRoomScreen): return .complete - case (_, .presentRoom): return .room case (_, .dismissFlow): return .complete - case (.initial, .presentRoomDetails): return .roomDetails(isRoot: true) case (.room, .presentRoomDetails): return .roomDetails(isRoot: false) case (.roomDetails, .dismissRoomDetails): return .room - case (.roomDetails, .presentRoomDetailsEditScreen): return .roomDetailsEditScreen case (.roomDetailsEditScreen, .dismissRoomDetailsEditScreen): return .roomDetails(isRoot: false) - case (.roomDetails, .presentNotificationSettingsScreen): return .notificationSettings case (.notificationSettings, .dismissNotificationSettingsScreen): return .roomDetails(isRoot: false) - case (.notificationSettings, .presentGlobalNotificationSettingsScreen): return .globalNotificationSettings case (.globalNotificationSettings, .dismissGlobalNotificationSettingsScreen): return .notificationSettings - case (.roomDetails, .presentRoomMembersList): return .roomMembersList case (.roomMembersList, .dismissRoomMembersList): return .roomDetails(isRoot: false) - case (.room, .presentRoomMemberDetails(userID: let userID)): - return .roomMemberDetails(userID: userID, fromRoomMembersList: false) + return .roomMemberDetails(userID: userID, previousState: .room) case (.roomMembersList, .presentRoomMemberDetails(userID: let userID)): - return .roomMemberDetails(userID: userID, fromRoomMembersList: true) - case (.roomMemberDetails(_, let fromRoomMembersList), .dismissRoomMemberDetails): - return fromRoomMembersList ? .roomMembersList : .room - - case (.roomMemberDetails(_, fromRoomMembersList: false), .presentUserProfile(let userID)): - return .userProfile(userID: userID) - case (.userProfile, .dismissUserProfile): - return .room - + return .roomMemberDetails(userID: userID, previousState: .roomMembersList) + case (.roomMemberDetails(_, let previousState), .dismissRoomMemberDetails): + return previousState + case (.roomMemberDetails(_, let previousState), .presentUserProfile(let userID)): + return .userProfile(userID: userID, previousState: previousState) + 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 (.room, .presentReportContent(let itemID, let senderID)): return .reportContent(itemID: itemID, senderID: senderID) case (.reportContent, .dismissReportContent): return .room - case (.room, .presentMediaUploadPicker(let source)): return .mediaUploadPicker(source: source) case (.mediaUploadPicker, .dismissMediaUploadPicker): return .room - case (.mediaUploadPicker, .presentMediaUploadPreview(let fileURL)): return .mediaUploadPreview(fileURL: fileURL) case (.room, .presentMediaUploadPreview(let fileURL)): return .mediaUploadPreview(fileURL: fileURL) case (.mediaUploadPreview, .dismissMediaUploadPreview): return .room - case (.room, .presentEmojiPicker(let itemID, let selectedEmoji)): return .emojiPicker(itemID: itemID, selectedEmojis: selectedEmoji) case (.emojiPicker, .dismissEmojiPicker): return .room - case (.room, .presentMessageForwarding(let forwardingItem)): return .messageForwarding(forwardingItem: forwardingItem) case (.messageForwarding, .dismissMessageForwarding): return .room - case (.room, .presentMapNavigator): return .mapNavigator case (.mapNavigator, .dismissMapNavigator): return .room - case (.room, .presentPollForm): return .pollForm case (.pollForm, .dismissPollForm): return .room - case (.room, .presentPinnedEventsTimeline): return .pinnedEventsTimeline(previousState: .room) case (.roomDetails(let isRoot), .presentPinnedEventsTimeline): @@ -337,29 +313,29 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { case .details(let isRoot): return .roomDetails(isRoot: isRoot) } - case (.roomDetails, .presentPollsHistory): return .pollsHistory case (.pollsHistory, .dismissPollsHistory): return .roomDetails(isRoot: false) - case (.pollsHistory, .presentPollForm): return .pollsHistoryForm case (.pollsHistoryForm, .dismissPollForm): return .pollsHistory - case (.roomDetails, .presentRolesAndPermissionsScreen): 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 + case (.resolveSendFailure, .dismissResolveSendFailure): + return .room // Child flow - case (_, .startChildFlow(let roomID, _, _)): return .presentingChild(childRoomID: roomID, previousState: fromState) case (.presentingChild(_, let previousState), .dismissChildFlow): return previousState - default: return nil } @@ -373,11 +349,13 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { switch (context.fromState, context.event, context.toState) { case (_, .presentJoinRoomScreen(let via), .joinRoomScreen): presentJoinRoomScreen(via: via, animated: true) + case (_, .dismissJoinRoomScreen, .complete): dismissFlow(animated: animated) - case (_, .presentRoom(let focussedEventID), .room): - Task { await self.presentRoom(fromState: context.fromState, focussedEventID: focussedEventID, animated: animated) } + case (_, .presentRoom(let focussedEvent), .room): + Task { await self.presentRoom(fromState: context.fromState, focussedEvent: focussedEvent, animated: animated) } + case (_, .dismissFlow, .complete): dismissFlow(animated: animated) @@ -385,119 +363,158 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { (.room, .presentRoomDetails, .roomDetails(let isRoot)), (.roomDetails, .presentRoomDetails, .roomDetails(let isRoot)): Task { await self.presentRoomDetails(isRoot: isRoot, animated: animated) } + case (.roomDetails, .dismissRoomDetails, .room): break case (.roomDetails, .presentRoomDetailsEditScreen, .roomDetailsEditScreen): presentRoomDetailsEditScreen() + case (.roomDetailsEditScreen, .dismissRoomDetailsEditScreen, .roomDetails): break case (.roomDetails, .presentNotificationSettingsScreen, .notificationSettings): presentNotificationSettingsScreen() + case (.notificationSettings, .dismissNotificationSettingsScreen, .roomDetails): break case (.notificationSettings, .presentGlobalNotificationSettingsScreen, .globalNotificationSettings): presentGlobalNotificationSettingsScreen() + case (.globalNotificationSettings, .dismissGlobalNotificationSettingsScreen, .notificationSettings): break case (.roomDetails, .presentRoomMembersList, .roomMembersList): presentRoomMembersList() + case (.roomMembersList, .dismissRoomMembersList, .roomDetails): break case (.room, .presentRoomMemberDetails, .roomMemberDetails(let userID, _)): presentRoomMemberDetails(userID: userID) + case (.roomMemberDetails, .dismissRoomMemberDetails, .room): break case (.roomMembersList, .presentRoomMemberDetails, .roomMemberDetails(let userID, _)): presentRoomMemberDetails(userID: userID) + case (.roomMemberDetails, .dismissRoomMemberDetails, .roomMembersList): break case (.roomMemberDetails, .presentUserProfile(let userID), .userProfile): replaceRoomMemberDetailsWithUserProfile(userID: userID) + case (.userProfile, .dismissUserProfile, .room): break case (.roomDetails, .presentInviteUsersScreen, .inviteUsersScreen): presentInviteUsersScreen() + case (.inviteUsersScreen, .dismissInviteUsersScreen, .roomDetails): break case (.roomMembersList, .presentInviteUsersScreen, .inviteUsersScreen): presentInviteUsersScreen() + case (.inviteUsersScreen, .dismissInviteUsersScreen, .roomMembersList): break case (.room, .presentReportContent, .reportContent(let itemID, let senderID)): presentReportContent(for: itemID, from: senderID) + case (.reportContent, .dismissReportContent, .room): break case (.room, .presentMediaUploadPicker, .mediaUploadPicker(let source)): presentMediaUploadPickerWithSource(source) + case (.mediaUploadPicker, .dismissMediaUploadPicker, .room): break case (.mediaUploadPicker, .presentMediaUploadPreview, .mediaUploadPreview(let fileURL)): presentMediaUploadPreviewScreen(for: fileURL) + case (.room, .presentMediaUploadPreview, .mediaUploadPreview(let fileURL)): presentMediaUploadPreviewScreen(for: fileURL) + case (.mediaUploadPreview, .dismissMediaUploadPreview, .room): break case (.room, .presentEmojiPicker, .emojiPicker(let itemID, let selectedEmoji)): presentEmojiPicker(for: itemID, selectedEmoji: selectedEmoji) + case (.emojiPicker, .dismissEmojiPicker, .room): break case (.room, .presentMessageForwarding(let forwardingItem), .messageForwarding): presentMessageForwarding(with: forwardingItem) + case (.messageForwarding, .dismissMessageForwarding, .room): break case (.room, .presentMapNavigator(let mode), .mapNavigator): presentMapNavigator(interactionMode: mode) + case (.mapNavigator, .dismissMapNavigator, .room): break case (.room, .presentPollForm(let mode), .pollForm): presentPollForm(mode: mode) + case (.pollForm, .dismissPollForm, .room): break case (.room, .presentPinnedEventsTimeline, .pinnedEventsTimeline): presentPinnedEventsTimeline() + case (.pinnedEventsTimeline, .dismissPinnedEventsTimeline, .room): break case (.roomDetails, .presentPollsHistory, .pollsHistory): presentPollsHistory() + case (.pollsHistory, .dismissPollsHistory, .roomDetails): break case (.roomDetails, .presentPinnedEventsTimeline, .pinnedEventsTimeline): presentPinnedEventsTimeline() + case (.pinnedEventsTimeline, .dismissPinnedEventsTimeline, .roomDetails): break case (.pollsHistory, .presentPollForm(let mode), .pollsHistoryForm): presentPollForm(mode: mode) + case (.pollsHistoryForm, .dismissPollForm, .pollsHistory): break case (.roomDetails, .presentRolesAndPermissionsScreen, .rolesAndPermissions): presentRolesAndPermissionsScreen() + case (.rolesAndPermissions, .dismissRolesAndPermissionsScreen, .roomDetails): rolesAndPermissionsFlowCoordinator = nil + + case (.roomDetails, .presentRoomMemberDetails(let userID), .roomMemberDetails): + presentRoomMemberDetails(userID: userID) + + case (.roomMemberDetails, .dismissRoomMemberDetails, .roomDetails): + break + + case (.roomMemberDetails, .dismissUserProfile, .roomDetails): + break + + case (.room, .presentResolveSendFailure(let failure, let itemID), .resolveSendFailure): + presentResolveSendFailure(failure: failure, itemID: itemID) + + case (.resolveSendFailure, .dismissResolveSendFailure, .room): + break // Child flow case (_, .startChildFlow(let roomID, let via, let entryPoint), .presentingChild): Task { await self.startChildFlow(for: roomID, via: via, entryPoint: entryPoint) } + case (.presentingChild, .dismissChildFlow, _): childRoomFlowCoordinator = nil @@ -526,9 +543,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { /// Updates the navigation stack so it displays the timeline for the given room /// - Parameters: /// - fromState: The state that asked for the room presentation. - /// - focussedEventID: An (optional) event ID that the timeline should be focussed around. + /// - 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, focussedEventID: String? = nil, animated: Bool) async { + private func presentRoom(fromState: State, focussedEvent: FocusEvent?, 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) @@ -546,8 +563,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { // The room is already on the stack, no need to present it again // Check if we need to focus on an event - if let focussedEventID { - roomScreenCoordinator?.focusOnEvent(eventID: focussedEventID) + if let focussedEvent { + roomScreenCoordinator?.focusOnEvent(focussedEvent) } return @@ -562,12 +579,11 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { let userID = userSession.clientProxy.userID let timelineItemFactory = RoomTimelineItemFactory(userID: userID, - encryptionAuthenticityEnabled: appSettings.timelineItemAuthenticityEnabled, attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID)) let timelineController = roomTimelineControllerFactory.buildRoomTimelineController(roomProxy: roomProxy, - initialFocussedEventID: focussedEventID, + initialFocussedEventID: focussedEvent?.eventID, timelineItemFactory: timelineItemFactory) self.timelineController = timelineController @@ -578,13 +594,14 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { let composerDraftService = ComposerDraftService(roomProxy: roomProxy, timelineItemfactory: timelineItemFactory) let parameters = RoomScreenCoordinatorParameters(roomProxy: roomProxy, - focussedEventID: focussedEventID, + focussedEvent: focussedEvent, timelineController: timelineController, mediaProvider: userSession.mediaProvider, mediaPlayerProvider: MediaPlayerProvider(), voiceMessageMediaManager: userSession.voiceMessageMediaManager, emojiProvider: emojiProvider, completionSuggestionService: completionSuggestionService, + ongoingCallRoomIDPublisher: ongoingCallRoomIDPublisher, appMediator: appMediator, appSettings: appSettings, composerDraftService: composerDraftService) @@ -619,6 +636,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)) } } .store(in: &cancellables) @@ -659,9 +678,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { Task { [weak self] in guard let self else { return } - if let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) { + if case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomID) { await storeAndSubscribeToRoomProxy(roomProxy) - stateMachine.tryEvent(.presentRoom(focussedEventID: nil), userInfo: EventUserInfo(animated: animated)) + stateMachine.tryEvent(.presentRoom(focussedEvent: nil), userInfo: EventUserInfo(animated: animated)) analytics.trackJoinedRoom(isDM: roomProxy.isDirect, isSpace: roomProxy.isSpace, activeMemberCount: UInt(roomProxy.activeMembersCount)) } else { @@ -965,28 +984,6 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { } } - private func presentPinnedEventsTimeline() { - let stackCoordinator = NavigationStackCoordinator() - let coordinator = PinnedEventsTimelineScreenCoordinator(parameters: .init()) - - coordinator.actions - .sink { [weak self] action in - guard let self else { return } - - switch action { - case .dismiss: - navigationStackCoordinator.setSheetCoordinator(nil) - } - } - .store(in: &cancellables) - - stackCoordinator.setRootCoordinator(coordinator) - - navigationStackCoordinator.setSheetCoordinator(stackCoordinator) { [weak self] in - self?.stateMachine.tryEvent(.dismissPinnedEventsTimeline) - } - } - private func presentPollForm(mode: PollFormMode) { let stackCoordinator = NavigationStackCoordinator() let coordinator = PollFormScreenCoordinator(parameters: .init(mode: mode)) @@ -1083,7 +1080,6 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { let userID = userSession.clientProxy.userID let timelineItemFactory = RoomTimelineItemFactory(userID: userID, - encryptionAuthenticityEnabled: appSettings.timelineItemAuthenticityEnabled, attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID)) @@ -1288,7 +1284,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { } } - private func inviteUsers(_ users: [String], in room: RoomProxyProtocol) { + private func inviteUsers(_ users: [String], in room: JoinedRoomProxyProtocol) { navigationStackCoordinator.setSheetCoordinator(nil) Task { @@ -1333,6 +1329,63 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { coordinator.start() } + private func presentPinnedEventsTimeline() { + let stackCoordinator = NavigationStackCoordinator() + let coordinator = PinnedEventsTimelineFlowCoordinator(navigationStackCoordinator: stackCoordinator, + userSession: userSession, + roomTimelineControllerFactory: roomTimelineControllerFactory, + roomProxy: roomProxy, + userIndicatorController: userIndicatorController, + appMediator: appMediator) + + coordinator.actionsPublisher.sink { [weak self] action in + guard let self else { + return + } + + switch action { + case .finished: + navigationStackCoordinator.setSheetCoordinator(nil) + case .displayUser(let userID): + navigationStackCoordinator.setSheetCoordinator(nil) + stateMachine.tryEvent(.presentRoomMemberDetails(userID: userID)) + case .forwardedMessageToRoom(let roomID): + navigationStackCoordinator.setSheetCoordinator(nil) + stateMachine.tryEvent(.startChildFlow(roomID: roomID, via: [], entryPoint: .room)) + case .displayRoomScreenWithFocussedPin(let eventID): + navigationStackCoordinator.setSheetCoordinator(nil) + stateMachine.tryEvent(.presentRoom(focussedEvent: .init(eventID: eventID, shouldSetPin: true))) + } + } + .store(in: &cancellables) + + pinnedEventsTimelineFlowCoordinator = coordinator + navigationStackCoordinator.setSheetCoordinator(stackCoordinator) { [weak self] in + self?.stateMachine.tryEvent(.dismissPinnedEventsTimeline) + } + coordinator.start() + } + + private func presentResolveSendFailure(failure: TimelineItemSendFailure.VerifiedUser, itemID: TimelineItemIdentifier) { + let coordinator = ResolveVerifiedUserSendFailureScreenCoordinator(parameters: .init(failure: failure, + itemID: itemID, + roomProxy: roomProxy, + userIndicatorController: userIndicatorController)) + coordinator.actionsPublisher.sink { [weak self] action in + guard let self else { return } + + switch action { + case .dismiss: + navigationStackCoordinator.setSheetCoordinator(nil) + } + } + .store(in: &cancellables) + + navigationStackCoordinator.setSheetCoordinator(coordinator) { [weak self] in + self?.stateMachine.tryEvent(.dismissResolveSendFailure) + } + } + // MARK: - Child Flow private func startChildFlow(for roomID: String, via: [String], entryPoint: RoomFlowCoordinatorEntryPoint) async { @@ -1342,6 +1395,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { roomTimelineControllerFactory: roomTimelineControllerFactory, navigationStackCoordinator: navigationStackCoordinator, emojiProvider: emojiProvider, + ongoingCallRoomIDPublisher: ongoingCallRoomIDPublisher, appMediator: appMediator, appSettings: appSettings, analytics: analytics, @@ -1392,8 +1446,8 @@ private extension RoomFlowCoordinator { case notificationSettings case globalNotificationSettings case roomMembersList - case roomMemberDetails(userID: String, fromRoomMembersList: Bool) - case userProfile(userID: String) + case roomMemberDetails(userID: String, previousState: State) + case userProfile(userID: String, previousState: State) case inviteUsersScreen(fromRoomMembersList: Bool) case mediaUploadPicker(source: MediaPickerScreenSource) case mediaUploadPreview(fileURL: URL) @@ -1406,6 +1460,7 @@ private extension RoomFlowCoordinator { case pollsHistoryForm case rolesAndPermissions case pinnedEventsTimeline(previousState: PinnedEventsTimelineSource) + case resolveSendFailure /// A child flow is in progress. case presentingChild(childRoomID: String, previousState: State) @@ -1421,7 +1476,7 @@ private extension RoomFlowCoordinator { case presentJoinRoomScreen(via: [String]) case dismissJoinRoomScreen - case presentRoom(focussedEventID: String?) + case presentRoom(focussedEvent: FocusEvent?) case dismissFlow case presentReportContent(itemID: TimelineItemIdentifier, senderID: String) @@ -1478,18 +1533,15 @@ private extension RoomFlowCoordinator { case presentPinnedEventsTimeline case dismissPinnedEventsTimeline + case presentResolveSendFailure(failure: TimelineItemSendFailure.VerifiedUser, itemID: TimelineItemIdentifier) + case dismissResolveSendFailure + // Child room flow events case startChildFlow(roomID: String, via: [String], entryPoint: RoomFlowCoordinatorEntryPoint) case dismissChildFlow } } -private extension GeoURI { - var bodyMessage: String { - "Location was shared at \(string)" - } -} - private extension Result { var isFailure: Bool { switch self { @@ -1505,3 +1557,10 @@ 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/RoomRolesAndPermissionsFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/RoomRolesAndPermissionsFlowCoordinator.swift index eedf252c3f..ba8418fef8 100644 --- a/ElementX/Sources/FlowCoordinators/RoomRolesAndPermissionsFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/RoomRolesAndPermissionsFlowCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -24,7 +15,7 @@ enum RoomRolesAndPermissionsFlowCoordinatorAction: Equatable { } struct RoomRolesAndPermissionsFlowCoordinatorParameters { - let roomProxy: RoomProxyProtocol + let roomProxy: JoinedRoomProxyProtocol let mediaProvider: MediaProviderProtocol let navigationStackCoordinator: NavigationStackCoordinator let userIndicatorController: UserIndicatorControllerProtocol @@ -32,7 +23,7 @@ struct RoomRolesAndPermissionsFlowCoordinatorParameters { } class RoomRolesAndPermissionsFlowCoordinator: FlowCoordinatorProtocol { - private let roomProxy: RoomProxyProtocol + private let roomProxy: JoinedRoomProxyProtocol private let navigationStackCoordinator: NavigationStackCoordinator private let mediaProvider: MediaProviderProtocol private let userIndicatorController: UserIndicatorControllerProtocol diff --git a/ElementX/Sources/FlowCoordinators/SettingsFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/SettingsFlowCoordinator.swift index 07489230e5..e78d5ab59f 100644 --- a/ElementX/Sources/FlowCoordinators/SettingsFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/SettingsFlowCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -135,6 +126,8 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol { presentAdvancedSettings() case .developerOptions: presentDeveloperOptions() + case .deactivateAccount: + presentDeactivateAccount() } } .store(in: &cancellables) @@ -232,7 +225,7 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol { } private func presentDeveloperOptions() { - let coordinator = DeveloperOptionsScreenCoordinator() + let coordinator = DeveloperOptionsScreenCoordinator(isUsingNativeSlidingSync: parameters.userSession.clientProxy.slidingSyncVersion == .native) coordinator.actions .sink { [weak self] action in @@ -241,7 +234,24 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol { switch action { case .clearCache: actionsSubject.send(.clearCache) - case .forceLogout: + } + } + .store(in: &cancellables) + + navigationStackCoordinator.push(coordinator) + } + + private func presentDeactivateAccount() { + let parameters = DeactivateAccountScreenCoordinatorParameters(clientProxy: parameters.userSession.clientProxy, + userIndicatorController: parameters.userIndicatorController) + let coordinator = DeactivateAccountScreenCoordinator(parameters: parameters) + + coordinator.actionsPublisher + .sink { [weak self] action in + guard let self else { return } + + switch action { + case .accountDeactivated: actionsSubject.send(.forceLogout) } } diff --git a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift index e052050fe5..1f5f8137ff 100644 --- a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift @@ -1,19 +1,11 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // +import AVKit import Combine import SwiftUI @@ -184,6 +176,17 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { } } .store(in: &cancellables) + + onboardingFlowCoordinator.actions + .sink { [weak self] action in + guard let self else { return } + + switch action { + case .logout: + logout() + } + } + .store(in: &cancellables) } func start() { @@ -237,7 +240,6 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { case .success(let resolved): await asyncHandleAppRoute(.childRoom(roomID: resolved.roomId, via: resolved.servers), animated: animated) case .failure: showFailureIndicator() } - case .roomDetails(let roomID): if stateMachine.state.selectedRoomID == roomID { roomFlowCoordinator?.handleAppRoute(appRoute, animated: animated) @@ -255,7 +257,6 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { case .success(let resolved): await asyncHandleAppRoute(.event(eventID: eventID, roomID: resolved.roomId, via: resolved.servers), animated: animated) case .failure: showFailureIndicator() } - case .childEvent: roomFlowCoordinator?.handleAppRoute(appRoute, animated: animated) case .childEventOnRoomAlias(let eventID, let alias): @@ -263,15 +264,12 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { case .success(let resolved): await asyncHandleAppRoute(.childEvent(eventID: eventID, roomID: resolved.roomId, via: resolved.servers), animated: animated) case .failure: showFailureIndicator() } - 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) } case .genericCallLink(let url): - navigationSplitCoordinator.setSheetCoordinator(GenericCallLinkCoordinator(parameters: .init(url: url)), animated: animated) + presentCallScreen(genericCallLink: url) case .settings, .chatBackupSettings: settingsFlowCoordinator.handleAppRoute(appRoute, animated: animated) case .oidcCallback: @@ -318,14 +316,13 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { } else { Task { await self.startRoomFlow(roomID: roomID, via: via, entryPoint: entryPoint, animated: animated) } } + hideCallScreenOverlay() // Turn any active call into a PiP so that navigation from a notification is visible to the user. case(.roomList, .deselectRoom, .roomList): dismissRoomFlow(animated: animated) - case (.roomList, .showSettingsScreen, .settingsScreen): break case (.settingsScreen, .dismissedSettingsScreen, .roomList): break - case (.roomList, .feedbackScreen, .feedbackScreen): bugReportFlowCoordinator = BugReportFlowCoordinator(parameters: .init(presentationMode: .sheet(sidebarNavigationStackCoordinator), userIndicatorController: ServiceLocator.shared.userIndicatorController, @@ -334,27 +331,22 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { bugReportFlowCoordinator?.start() case (.feedbackScreen, .dismissedFeedbackScreen, .roomList): break - case (.roomList, .showStartChatScreen, .startChatScreen): presentStartChat(animated: animated) case (.startChatScreen, .dismissedStartChatScreen, .roomList): break - case (.roomList, .showLogoutConfirmationScreen, .logoutConfirmationScreen): presentSecureBackupLogoutConfirmationScreen() case (.logoutConfirmationScreen, .dismissedLogoutConfirmationScreen, .roomList): break - case (.roomList, .showRoomDirectorySearchScreen, .roomDirectorySearchScreen): presentRoomDirectorySearch() case (.roomDirectorySearchScreen, .dismissedRoomDirectorySearchScreen, .roomList): dismissRoomDirectorySearch() - case (_, .showUserProfileScreen(let userID), .userProfileScreen): presentUserProfileScreen(userID: userID, animated: animated) case (.userProfileScreen, .dismissedUserProfileScreen, .roomList): break - default: fatalError("Unknown transition: \(context)") } @@ -406,12 +398,14 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { settingsFlowCoordinator.handleAppRoute(.chatBackupSettings, animated: true) case .presentStartChatScreen: stateMachine.processEvent(.showStartChatScreen) - case .logout: - Task { await self.runLogoutFlow() } case .presentGlobalSearch: presentGlobalSearch() case .presentRoomDirectorySearch: stateMachine.processEvent(.showRoomDirectorySearchScreen) + case .logoutWithoutConfirmation: + self.actionsSubject.send(.logout) + case .logout: + Task { await self.runLogoutFlow() } } } .store(in: &cancellables) @@ -430,12 +424,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { } guard isLastDevice else { - ServiceLocator.shared.userIndicatorController.alertInfo = .init(id: .init(), - title: L10n.screenSignoutConfirmationDialogTitle, - message: L10n.screenSignoutConfirmationDialogContent, - primaryButton: .init(title: L10n.screenSignoutConfirmationDialogSubmit, role: .destructive) { [weak self] in - self?.actionsSubject.send(.logout) - }) + logout() return } @@ -466,6 +455,15 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { presentSecureBackupLogoutConfirmationScreen() } + private func logout() { + ServiceLocator.shared.userIndicatorController.alertInfo = .init(id: .init(), + title: L10n.screenSignoutConfirmationDialogTitle, + message: L10n.screenSignoutConfirmationDialogContent, + primaryButton: .init(title: L10n.screenSignoutConfirmationDialogSubmit, role: .destructive) { [weak self] in + self?.actionsSubject.send(.logout) + }) + } + // MARK: Room Flow private func startRoomFlow(roomID: String, @@ -478,6 +476,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { roomTimelineControllerFactory: roomTimelineControllerFactory, navigationStackCoordinator: detailNavigationStackCoordinator, emojiProvider: EmojiProvider(), + ongoingCallRoomIDPublisher: elementCallService.ongoingCallRoomIDPublisher, appMediator: appMediator, appSettings: appSettings, analytics: analytics, @@ -557,45 +556,83 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { // MARK: Calls - private func presentCallScreen(roomProxy: RoomProxyProtocol) { + private func presentCallScreen(genericCallLink url: URL) { + presentCallScreen(configuration: .init(genericCallLink: url)) + } + + private func presentCallScreen(roomID: String) async { + guard case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomID) else { + return + } + + presentCallScreen(roomProxy: roomProxy) + } + + private func presentCallScreen(roomProxy: JoinedRoomProxyProtocol) { 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)) + } + + private var callScreenPictureInPictureController: AVPictureInPictureController? + private func presentCallScreen(configuration: ElementCallConfiguration) { + guard elementCallService.ongoingCallRoomIDPublisher.value != configuration.callRoomID else { + MXLog.info("Returning to existing call.") + callScreenPictureInPictureController?.stopPictureInPicture() + return + } + let callScreenCoordinator = CallScreenCoordinator(parameters: .init(elementCallService: elementCallService, - clientProxy: userSession.clientProxy, - roomProxy: roomProxy, - clientID: InfoPlistReader.main.bundleIdentifier, - elementCallBaseURL: appSettings.elementCallBaseURL, - elementCallBaseURLOverride: appSettings.elementCallBaseURLOverride, - colorScheme: colorScheme, + configuration: configuration, + allowPictureInPicture: true, appHooks: appHooks)) callScreenCoordinator.actions .sink { [weak self] action in + guard let self else { return } switch action { + case .pictureInPictureIsAvailable(let controller): + callScreenPictureInPictureController = controller + case .pictureInPictureStarted: + MXLog.info("Hiding call for PiP presentation.") + navigationSplitCoordinator.setOverlayPresentationMode(.minimized) + case .pictureInPictureStopped: + MXLog.info("Restoring call after PiP presentation.") + navigationSplitCoordinator.setOverlayPresentationMode(.fullScreen) case .dismiss: - self?.navigationSplitCoordinator.setSheetCoordinator(nil) + callScreenPictureInPictureController = nil + navigationSplitCoordinator.setOverlayCoordinator(nil) } } .store(in: &cancellables) - navigationSplitCoordinator.setSheetCoordinator(callScreenCoordinator, animated: true) + navigationSplitCoordinator.setOverlayCoordinator(callScreenCoordinator, animated: true) analytics.track(screen: .RoomCall) } - private func presentCallScreen(roomID: String) async { - guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) else { + private func hideCallScreenOverlay() { + guard let callScreenPictureInPictureController else { + MXLog.warning("Picture in picture isn't available, dismissing the call screen.") + dismissCallScreenIfNeeded() return } - presentCallScreen(roomProxy: roomProxy) + MXLog.info("Starting picture in picture to hide the call screen overlay.") + callScreenPictureInPictureController.startPictureInPicture() + navigationSplitCoordinator.setOverlayPresentationMode(.minimized) } private func dismissCallScreenIfNeeded() { - guard navigationSplitCoordinator.sheetCoordinator is CallScreenCoordinator else { + guard navigationSplitCoordinator.overlayCoordinator is CallScreenCoordinator else { return } - navigationSplitCoordinator.setSheetCoordinator(nil) + navigationSplitCoordinator.setOverlayCoordinator(nil) } // MARK: Secure backup confirmation @@ -666,7 +703,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { private func presentRoomDirectorySearch() { let coordinator = RoomDirectorySearchScreenCoordinator(parameters: .init(clientProxy: userSession.clientProxy, - imageProvider: userSession.mediaProvider, + mediaProvider: userSession.mediaProvider, userIndicatorController: ServiceLocator.shared.userIndicatorController)) coordinator.actionsPublisher.sink { [weak self] action in diff --git a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinatorStateMachine.swift b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinatorStateMachine.swift index 78afe9de9b..652d1e5992 100644 --- a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinatorStateMachine.swift +++ b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinatorStateMachine.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -132,36 +123,43 @@ class UserSessionFlowCoordinatorStateMachine { switch (fromState, event) { case (.roomList, .selectRoom(let roomID, _, _)): return .roomList(selectedRoomID: roomID) + case (.roomList, .deselectRoom): return .roomList(selectedRoomID: nil) case (.roomList(let selectedRoomID), .showSettingsScreen): return .settingsScreen(selectedRoomID: selectedRoomID) + case (.settingsScreen(let selectedRoomID), .dismissedSettingsScreen): return .roomList(selectedRoomID: selectedRoomID) case (.roomList(let selectedRoomID), .feedbackScreen): return .feedbackScreen(selectedRoomID: selectedRoomID) + case (.feedbackScreen(let selectedRoomID), .dismissedFeedbackScreen): return .roomList(selectedRoomID: selectedRoomID) case (.roomList(let selectedRoomID), .showStartChatScreen): return .startChatScreen(selectedRoomID: selectedRoomID) + case (.startChatScreen(let selectedRoomID), .dismissedStartChatScreen): return .roomList(selectedRoomID: selectedRoomID) case (.roomList(let selectedRoomID), .showLogoutConfirmationScreen): return .logoutConfirmationScreen(selectedRoomID: selectedRoomID) + case (.logoutConfirmationScreen(let selectedRoomID), .dismissedLogoutConfirmationScreen): return .roomList(selectedRoomID: selectedRoomID) case (.roomList(let selectedRoomID), .showRoomDirectorySearchScreen): return .roomDirectorySearchScreen(selectedRoomID: selectedRoomID) + case (.roomDirectorySearchScreen(let selectedRoomID), .dismissedRoomDirectorySearchScreen): return .roomList(selectedRoomID: selectedRoomID) case (_, .showUserProfileScreen): return .userProfileScreen + case (.userProfileScreen, .dismissedUserProfileScreen): return .roomList(selectedRoomID: nil) diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index a88f3f4042..23d1461ba7 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -84,6 +84,8 @@ internal enum L10n { internal static var actionCall: String { return L10n.tr("Localizable", "action_call") } /// Cancel internal static var actionCancel: String { return L10n.tr("Localizable", "action_cancel") } + /// Cancel for now + internal static var actionCancelForNow: String { return L10n.tr("Localizable", "action_cancel_for_now") } /// Choose photo internal static var actionChoosePhoto: String { return L10n.tr("Localizable", "action_choose_photo") } /// Clear @@ -94,6 +96,8 @@ internal enum L10n { internal static var actionCompleteVerification: String { return L10n.tr("Localizable", "action_complete_verification") } /// Confirm internal static var actionConfirm: String { return L10n.tr("Localizable", "action_confirm") } + /// Confirm password + internal static var actionConfirmPassword: String { return L10n.tr("Localizable", "action_confirm_password") } /// Continue internal static var actionContinue: String { return L10n.tr("Localizable", "action_continue") } /// Copy @@ -106,6 +110,10 @@ internal enum L10n { internal static var actionCreate: String { return L10n.tr("Localizable", "action_create") } /// Create a room internal static var actionCreateARoom: String { return L10n.tr("Localizable", "action_create_a_room") } + /// Deactivate + internal static var actionDeactivate: String { return L10n.tr("Localizable", "action_deactivate") } + /// Deactivate account + internal static var actionDeactivateAccount: String { return L10n.tr("Localizable", "action_deactivate_account") } /// Decline internal static var actionDecline: String { return L10n.tr("Localizable", "action_decline") } /// Delete Poll @@ -238,10 +246,20 @@ internal enum L10n { internal static var actionTryAgain: String { return L10n.tr("Localizable", "action_try_again") } /// Unpin internal static var actionUnpin: String { return L10n.tr("Localizable", "action_unpin") } + /// View in timeline + internal static var actionViewInTimeline: String { return L10n.tr("Localizable", "action_view_in_timeline") } /// View source internal static var actionViewSource: String { return L10n.tr("Localizable", "action_view_source") } /// Yes internal static var actionYes: String { return L10n.tr("Localizable", "action_yes") } + /// Log Out & Upgrade + internal static var bannerMigrateToNativeSlidingSyncAction: String { return L10n.tr("Localizable", "banner_migrate_to_native_sliding_sync_action") } + /// Your server now supports a new, faster protocol. Log out and log back in to upgrade now. Doing this now will help you avoid a forced logout when the old protocol is removed later. + internal static var bannerMigrateToNativeSlidingSyncDescription: String { return L10n.tr("Localizable", "banner_migrate_to_native_sliding_sync_description") } + /// Your homeserver no longer supports the old protocol. Please log out and log back in to continue using the app. + internal static var bannerMigrateToNativeSlidingSyncForceLogoutTitle: String { return L10n.tr("Localizable", "banner_migrate_to_native_sliding_sync_force_logout_title") } + /// Upgrade available + internal static var bannerMigrateToNativeSlidingSyncTitle: String { return L10n.tr("Localizable", "banner_migrate_to_native_sliding_sync_title") } /// About internal static var commonAbout: String { return L10n.tr("Localizable", "common_about") } /// Acceptable use policy @@ -546,6 +564,8 @@ internal enum L10n { internal static var emojiPickerCategoryPlaces: String { return L10n.tr("Localizable", "emoji_picker_category_places") } /// Symbols internal static var emojiPickerCategorySymbols: String { return L10n.tr("Localizable", "emoji_picker_category_symbols") } + /// Your homeserver needs to be upgraded to support Matrix Authentication Service and account creation. + internal static var errorAccountCreationNotPossible: String { return L10n.tr("Localizable", "error_account_creation_not_possible") } /// Failed creating the permalink internal static var errorFailedCreatingThePermalink: String { return L10n.tr("Localizable", "error_failed_creating_the_permalink") } /// %1$@ could not load the map. Please try again later. @@ -570,6 +590,8 @@ internal enum L10n { internal static var errorUnknown: String { return L10n.tr("Localizable", "error_unknown") } /// The authenticity of this encrypted message can't be guaranteed on this device. internal static var eventShieldReasonAuthenticityNotGuaranteed: String { return L10n.tr("Localizable", "event_shield_reason_authenticity_not_guaranteed") } + /// Encrypted by a previously-verified user. + internal static var eventShieldReasonPreviouslyVerified: String { return L10n.tr("Localizable", "event_shield_reason_previously_verified") } /// Not encrypted. internal static var eventShieldReasonSentInClear: String { return L10n.tr("Localizable", "event_shield_reason_sent_in_clear") } /// Encrypted by an unknown or deleted device. @@ -638,6 +660,10 @@ internal enum L10n { } /// Invited you to chat internal static var notificationInviteBody: String { return L10n.tr("Localizable", "notification_invite_body") } + /// %1$@ invited you to chat + internal static func notificationInviteBodyWithSender(_ p1: Any) -> String { + return L10n.tr("Localizable", "notification_invite_body_with_sender", String(describing: p1)) + } /// Mentioned you: %1$@ internal static func notificationMentionedYouBody(_ p1: Any) -> String { return L10n.tr("Localizable", "notification_mentioned_you_body", String(describing: p1)) @@ -658,8 +684,16 @@ internal enum L10n { internal static var notificationRoomActionQuickReply: String { return L10n.tr("Localizable", "notification_room_action_quick_reply") } /// Invited you to join the room internal static var notificationRoomInviteBody: String { return L10n.tr("Localizable", "notification_room_invite_body") } + /// %1$@ invited you to join the room + internal static func notificationRoomInviteBodyWithSender(_ p1: Any) -> String { + return L10n.tr("Localizable", "notification_room_invite_body_with_sender", String(describing: p1)) + } /// Me internal static var notificationSenderMe: String { return L10n.tr("Localizable", "notification_sender_me") } + /// %1$@ mentioned or replied + internal static func notificationSenderMentionReply(_ p1: Any) -> String { + return L10n.tr("Localizable", "notification_sender_mention_reply", String(describing: p1)) + } /// You are viewing the notification! Click me! internal static var notificationTestPushNotificationContent: String { return L10n.tr("Localizable", "notification_test_push_notification_content") } /// %1$@: %2$@ @@ -961,6 +995,8 @@ internal enum L10n { internal static func screenChatBackupRecoveryActionSetupDescription(_ p1: Any) -> String { return L10n.tr("Localizable", "screen_chat_backup_recovery_action_setup_description", String(describing: p1)) } + /// Create account + internal static var screenCreateAccountTitle: String { return L10n.tr("Localizable", "screen_create_account_title") } /// Open %1$@ in a desktop device internal static func screenCreateNewRecoveryKeyListItem1(_ p1: Any) -> String { return L10n.tr("Localizable", "screen_create_new_recovery_key_list_item_1", String(describing: p1)) @@ -1019,6 +1055,32 @@ internal enum L10n { internal static var screenCreateRoomTitle: String { return L10n.tr("Localizable", "screen_create_room_title") } /// Topic (optional) internal static var screenCreateRoomTopicLabel: String { return L10n.tr("Localizable", "screen_create_room_topic_label") } + /// Please confirm that you want to deactivate your account. This action cannot be undone. + internal static var screenDeactivateAccountConfirmationDialogContent: String { return L10n.tr("Localizable", "screen_deactivate_account_confirmation_dialog_content") } + /// Delete all my messages + internal static var screenDeactivateAccountDeleteAllMessages: String { return L10n.tr("Localizable", "screen_deactivate_account_delete_all_messages") } + /// Warning: Future users may see incomplete conversations. + internal static var screenDeactivateAccountDeleteAllMessagesNotice: String { return L10n.tr("Localizable", "screen_deactivate_account_delete_all_messages_notice") } + /// Deactivating your account is %1$@, it will: + internal static func screenDeactivateAccountDescription(_ p1: Any) -> String { + return L10n.tr("Localizable", "screen_deactivate_account_description", String(describing: p1)) + } + /// irreversible + internal static var screenDeactivateAccountDescriptionBoldPart: String { return L10n.tr("Localizable", "screen_deactivate_account_description_bold_part") } + /// %1$@ your account (you can't log back in, and your ID can't be reused). + internal static func screenDeactivateAccountListItem1(_ p1: Any) -> String { + return L10n.tr("Localizable", "screen_deactivate_account_list_item_1", String(describing: p1)) + } + /// Permanently disable + internal static var screenDeactivateAccountListItem1BoldPart: String { return L10n.tr("Localizable", "screen_deactivate_account_list_item_1_bold_part") } + /// Remove you from all chat rooms. + internal static var screenDeactivateAccountListItem2: String { return L10n.tr("Localizable", "screen_deactivate_account_list_item_2") } + /// Delete your account information from our identity server. + internal static var screenDeactivateAccountListItem3: String { return L10n.tr("Localizable", "screen_deactivate_account_list_item_3") } + /// 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. + internal static var screenDeactivateAccountListItem4: String { return L10n.tr("Localizable", "screen_deactivate_account_list_item_4") } + /// Deactivate account + internal static var screenDeactivateAccountTitle: String { return L10n.tr("Localizable", "screen_deactivate_account_title") } /// Block internal static var screenDmDetailsBlockAlertAction: String { return L10n.tr("Localizable", "screen_dm_details_block_alert_action") } /// Blocked users won't be able to send you messages and all their messages will be hidden. You can unblock them anytime. @@ -1049,6 +1111,8 @@ internal enum L10n { internal static var screenEditProfileTitle: String { return L10n.tr("Localizable", "screen_edit_profile_title") } /// Updating profileโ€ฆ internal static var screenEditProfileUpdatingDetails: String { return L10n.tr("Localizable", "screen_edit_profile_updating_details") } + /// Continue reset + internal static var screenEncryptionResetActionContinueReset: String { return L10n.tr("Localizable", "screen_encryption_reset_action_continue_reset") } /// Your account details, contacts, preferences, and chat list will be kept internal static var screenEncryptionResetBullet1: String { return L10n.tr("Localizable", "screen_encryption_reset_bullet_1") } /// You will lose your existing message history @@ -1057,9 +1121,7 @@ internal enum L10n { internal static var screenEncryptionResetBullet3: String { return L10n.tr("Localizable", "screen_encryption_reset_bullet_3") } /// Only reset your identity if you donโ€™t have access to another signed-in device and youโ€™ve lost your recovery key. internal static var screenEncryptionResetFooter: String { return L10n.tr("Localizable", "screen_encryption_reset_footer") } - /// If youโ€™re not signed in to any other devices and youโ€™ve lost your recovery key, then youโ€™ll need to reset your identity to continue using the app. - internal static var screenEncryptionResetSubtitle: String { return L10n.tr("Localizable", "screen_encryption_reset_subtitle") } - /// Reset your identity in case you canโ€™t confirm another way + /// Can't confirm? Youโ€™ll need to reset your identity. internal static var screenEncryptionResetTitle: String { return L10n.tr("Localizable", "screen_encryption_reset_title") } /// Can't confirm? internal static var screenIdentityConfirmationCannotConfirm: String { return L10n.tr("Localizable", "screen_identity_confirmation_cannot_confirm") } @@ -1067,7 +1129,7 @@ internal enum L10n { internal static var screenIdentityConfirmationCreateNewRecoveryKey: String { return L10n.tr("Localizable", "screen_identity_confirmation_create_new_recovery_key") } /// Verify this device to set up secure messaging. internal static var screenIdentityConfirmationSubtitle: String { return L10n.tr("Localizable", "screen_identity_confirmation_subtitle") } - /// Confirm that it's you + /// Confirm your identity internal static var screenIdentityConfirmationTitle: String { return L10n.tr("Localizable", "screen_identity_confirmation_title") } /// Use another device internal static var screenIdentityConfirmationUseAnotherDevice: String { return L10n.tr("Localizable", "screen_identity_confirmation_use_another_device") } @@ -1375,8 +1437,6 @@ internal enum L10n { internal static var screenRecoveryKeyConfirmErrorTitle: String { return L10n.tr("Localizable", "screen_recovery_key_confirm_error_title") } /// If you have a security key or security phrase, this will work too. internal static var screenRecoveryKeyConfirmKeyDescription: String { return L10n.tr("Localizable", "screen_recovery_key_confirm_key_description") } - /// Recovery key or passcode - internal static var screenRecoveryKeyConfirmKeyLabel: String { return L10n.tr("Localizable", "screen_recovery_key_confirm_key_label") } /// Enterโ€ฆ internal static var screenRecoveryKeyConfirmKeyPlaceholder: String { return L10n.tr("Localizable", "screen_recovery_key_confirm_key_placeholder") } /// Lost your recovery key? @@ -1423,14 +1483,46 @@ internal enum L10n { internal static var screenResetEncryptionConfirmationAlertAction: String { return L10n.tr("Localizable", "screen_reset_encryption_confirmation_alert_action") } /// This process is irreversible. internal static var screenResetEncryptionConfirmationAlertSubtitle: String { return L10n.tr("Localizable", "screen_reset_encryption_confirmation_alert_subtitle") } - /// Are you sure you want to reset your encryption? + /// Are you sure you want to reset your identity? internal static var screenResetEncryptionConfirmationAlertTitle: String { return L10n.tr("Localizable", "screen_reset_encryption_confirmation_alert_title") } + /// An unknown error happened. Please check your account password is correct and try again. + internal static var screenResetEncryptionPasswordError: String { return L10n.tr("Localizable", "screen_reset_encryption_password_error") } /// Enterโ€ฆ internal static var screenResetEncryptionPasswordPlaceholder: String { return L10n.tr("Localizable", "screen_reset_encryption_password_placeholder") } - /// Confirm that you want to reset your encryption. + /// Confirm that you want to reset your identity. internal static var screenResetEncryptionPasswordSubtitle: String { return L10n.tr("Localizable", "screen_reset_encryption_password_subtitle") } /// Enter your account password to continue internal static var screenResetEncryptionPasswordTitle: String { return L10n.tr("Localizable", "screen_reset_encryption_password_title") } + /// You're about to go to your %1$@ account to reset your identity. Afterwards you'll be taken back to the app. + internal static func screenResetIdentityConfirmationSubtitle(_ p1: Any) -> String { + return L10n.tr("Localizable", "screen_reset_identity_confirmation_subtitle", String(describing: p1)) + } + /// Can't confirm? Go to your account to reset your identity. + internal static var screenResetIdentityConfirmationTitle: String { return L10n.tr("Localizable", "screen_reset_identity_confirmation_title") } + /// Withdraw verification and send + internal static var screenResolveSendFailureChangedIdentityPrimaryButtonTitle: String { return L10n.tr("Localizable", "screen_resolve_send_failure_changed_identity_primary_button_title") } + /// You can withdraw your verification and send this message anyway, or you can cancel for now and try again later after reverifying %1$@. + internal static func screenResolveSendFailureChangedIdentitySubtitle(_ p1: Any) -> String { + return L10n.tr("Localizable", "screen_resolve_send_failure_changed_identity_subtitle", String(describing: p1)) + } + /// Your message was not sent because %1$@โ€™s verified identity has changed + internal static func screenResolveSendFailureChangedIdentityTitle(_ p1: Any) -> String { + return L10n.tr("Localizable", "screen_resolve_send_failure_changed_identity_title", String(describing: p1)) + } + /// Send message anyway + internal static var screenResolveSendFailureUnsignedDevicePrimaryButtonTitle: String { return L10n.tr("Localizable", "screen_resolve_send_failure_unsigned_device_primary_button_title") } + /// %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. + internal static func screenResolveSendFailureUnsignedDeviceSubtitle(_ p1: Any, _ p2: Any) -> String { + return L10n.tr("Localizable", "screen_resolve_send_failure_unsigned_device_subtitle", String(describing: p1), String(describing: p2)) + } + /// Your message was not sent because %1$@ has not verified all devices + internal static func screenResolveSendFailureUnsignedDeviceTitle(_ p1: Any) -> String { + return L10n.tr("Localizable", "screen_resolve_send_failure_unsigned_device_title", String(describing: p1)) + } + /// 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. + internal static var screenResolveSendFailureYouUnsignedDeviceSubtitle: String { return L10n.tr("Localizable", "screen_resolve_send_failure_you_unsigned_device_subtitle") } + /// Your message was not sent because you have not verified one or more of your devices + internal static var screenResolveSendFailureYouUnsignedDeviceTitle: String { return L10n.tr("Localizable", "screen_resolve_send_failure_you_unsigned_device_title") } /// Failed to resolve room alias. internal static var screenRoomAliasResolverResolveAliasFailure: String { return L10n.tr("Localizable", "screen_room_alias_resolver_resolve_alias_failure") } /// Camera @@ -1929,22 +2021,18 @@ internal enum L10n { internal static var screenSignoutSaveRecoveryKeyTitle: String { return L10n.tr("Localizable", "screen_signout_save_recovery_key_title") } /// An error occurred when trying to start a chat internal static var screenStartChatErrorStartingChat: String { return L10n.tr("Localizable", "screen_start_chat_error_starting_chat") } - /// Location - internal static var screenViewLocationTitle: String { return L10n.tr("Localizable", "screen_view_location_title") } - /// There's a high demand for %1$@ on %2$@ at the moment. Come back to the app in a few days and try again. - /// - /// Thanks for your patience! - internal static func screenWaitlistMessage(_ p1: Any, _ p2: Any) -> String { - return L10n.tr("Localizable", "screen_waitlist_message", String(describing: p1), String(describing: p2)) + /// Message not sent because %1$@โ€™s verified identity has changed. + internal static func screenTimelineItemMenuSendFailureChangedIdentity(_ p1: Any) -> String { + return L10n.tr("Localizable", "screen_timeline_item_menu_send_failure_changed_identity", String(describing: p1)) } - /// Welcome to %1$@! - internal static func screenWaitlistMessageSuccess(_ p1: Any) -> String { - return L10n.tr("Localizable", "screen_waitlist_message_success", String(describing: p1)) + /// Message not sent because %1$@ has not verified all devices. + internal static func screenTimelineItemMenuSendFailureUnsignedDevice(_ p1: Any) -> String { + return L10n.tr("Localizable", "screen_timeline_item_menu_send_failure_unsigned_device", String(describing: p1)) } - /// Youโ€™re almost there. - internal static var screenWaitlistTitle: String { return L10n.tr("Localizable", "screen_waitlist_title") } - /// You're in. - internal static var screenWaitlistTitleSuccess: String { return L10n.tr("Localizable", "screen_waitlist_title_success") } + /// Message not sent because you have not verified one or more of your devices. + internal static var screenTimelineItemMenuSendFailureYouUnsignedDevice: String { return L10n.tr("Localizable", "screen_timeline_item_menu_send_failure_you_unsigned_device") } + /// Location + internal static var screenViewLocationTitle: String { return L10n.tr("Localizable", "screen_view_location_title") } /// Calls, polls, search and more will be added later this year. internal static var screenWelcomeBullet1: String { return L10n.tr("Localizable", "screen_welcome_bullet_1") } /// Message history for encrypted rooms isnโ€™t available yet. @@ -2313,11 +2401,22 @@ internal enum L10n { internal static var loadMore: String { return L10n.tr("Localizable", "action.load_more") } } + internal enum Banner { + internal enum SetUpRecovery { + /// Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices. + internal static var content: String { return L10n.tr("Localizable", "banner.set_up_recovery.content") } + /// Set up recovery + internal static var title: String { return L10n.tr("Localizable", "banner.set_up_recovery.title") } + } + } + internal enum Common { /// Do not show this again internal static var doNotShowThisAgain: String { return L10n.tr("Localizable", "common.do_not_show_this_again") } /// Open source licenses internal static var openSourceLicenses: String { return L10n.tr("Localizable", "common.open_source_licenses") } + /// Pinned + internal static var pinned: String { return L10n.tr("Localizable", "common.pinned") } /// Send to internal static var sendTo: String { return L10n.tr("Localizable", "common.send_to") } } diff --git a/ElementX/Sources/Mocks/AggregatedReactionMock.swift b/ElementX/Sources/Mocks/AggregatedReactionMock.swift index 852764b442..c0b23ce290 100644 --- a/ElementX/Sources/Mocks/AggregatedReactionMock.swift +++ b/ElementX/Sources/Mocks/AggregatedReactionMock.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Mocks/AppMediatorMock.swift b/ElementX/Sources/Mocks/AppMediatorMock.swift index 79f4db7d03..dd4a59463e 100644 --- a/ElementX/Sources/Mocks/AppMediatorMock.swift +++ b/ElementX/Sources/Mocks/AppMediatorMock.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UIKit diff --git a/ElementX/Sources/Mocks/ClientProxyMock.swift b/ElementX/Sources/Mocks/ClientProxyMock.swift index 9122ae7ed4..e727ba6af3 100644 --- a/ElementX/Sources/Mocks/ClientProxyMock.swift +++ b/ElementX/Sources/Mocks/ClientProxyMock.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -56,6 +47,7 @@ extension ClientProxyMock { isOnlyDeviceLeftReturnValue = .success(false) accountURLActionReturnValue = "https://matrix.org/account" + canDeactivateAccount = false directRoomForUserIDReturnValue = .failure(.sdkError(ClientProxyMockError.generic)) createDirectRoomWithExpectedRoomNameReturnValue = .failure(.sdkError(ClientProxyMockError.generic)) createRoomNameTopicIsRoomPrivateUserIDsAvatarURLReturnValue = .failure(.sdkError(ClientProxyMockError.generic)) @@ -72,6 +64,11 @@ extension ClientProxyMock { ignoreUserReturnValue = .success(()) unignoreUserReturnValue = .success(()) + slidingSyncVersion = .native + availableSlidingSyncVersionsClosure = { + [] + } + trackRecentlyVisitedRoomReturnValue = .success(()) recentlyVisitedRoomsReturnValue = .success([]) recentConversationCounterpartsReturnValue = [] @@ -94,7 +91,7 @@ extension ClientProxyMock { return nil } - return await RoomProxyMock(.init(id: room.id, name: room.name)) + return await .joined(JoinedRoomProxyMock(.init(id: room.id, name: room.name))) } } } diff --git a/ElementX/Sources/Mocks/ComposerDraftServiceMock.swift b/ElementX/Sources/Mocks/ComposerDraftServiceMock.swift index 8002829ffd..abc5f5d806 100644 --- a/ElementX/Sources/Mocks/ComposerDraftServiceMock.swift +++ b/ElementX/Sources/Mocks/ComposerDraftServiceMock.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Mocks/ElementCallServiceMock.swift b/ElementX/Sources/Mocks/ElementCallServiceMock.swift index 27b2e81255..63a71807e9 100644 --- a/ElementX/Sources/Mocks/ElementCallServiceMock.swift +++ b/ElementX/Sources/Mocks/ElementCallServiceMock.swift @@ -1,28 +1,22 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine import Foundation -struct ElementCallServiceMockConfiguration { } +struct ElementCallServiceMockConfiguration { + var ongoingCallRoomID: String? +} extension ElementCallServiceMock { convenience init(_ configuration: ElementCallServiceMockConfiguration) { self.init() underlyingActions = PassthroughSubject().eraseToAnyPublisher() + underlyingOngoingCallRoomIDPublisher = .init(.init(configuration.ongoingCallRoomID)) } } diff --git a/ElementX/Sources/Mocks/EventTimelineItemSDKMock.swift b/ElementX/Sources/Mocks/EventTimelineItemSDKMock.swift new file mode 100644 index 0000000000..fbeea26eb8 --- /dev/null +++ b/ElementX/Sources/Mocks/EventTimelineItemSDKMock.swift @@ -0,0 +1,29 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Foundation + +struct EventTimelineItemSDKMockConfiguration { + var eventID: String = UUID().uuidString +} + +extension EventTimelineItemSDKMock { + convenience init(configuration: EventTimelineItemSDKMockConfiguration) { + self.init() + eventIdReturnValue = configuration.eventID + isOwnReturnValue = false + timestampReturnValue = 0 + isEditableReturnValue = false + canBeRepliedToReturnValue = false + senderReturnValue = "" + senderProfileReturnValue = .pending + + let timelineItemContent = TimelineItemContentSDKMock() + timelineItemContent.kindReturnValue = .redactedMessage + contentReturnValue = timelineItemContent + } +} diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index 6fb962d284..ba521052fb 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -1925,6 +1925,33 @@ class ClientProxyMock: ClientProxyProtocol { set(value) { underlyingHomeserver = value } } var underlyingHomeserver: String! + var slidingSyncVersion: SlidingSyncVersion { + get { return underlyingSlidingSyncVersion } + set(value) { underlyingSlidingSyncVersion = value } + } + var underlyingSlidingSyncVersion: SlidingSyncVersion! + var availableSlidingSyncVersionsCallsCount = 0 + var availableSlidingSyncVersionsCalled: Bool { + return availableSlidingSyncVersionsCallsCount > 0 + } + + var availableSlidingSyncVersions: [SlidingSyncVersion] { + get async { + availableSlidingSyncVersionsCallsCount += 1 + if let availableSlidingSyncVersionsClosure = availableSlidingSyncVersionsClosure { + return await availableSlidingSyncVersionsClosure() + } else { + return underlyingAvailableSlidingSyncVersions + } + } + } + var underlyingAvailableSlidingSyncVersions: [SlidingSyncVersion]! + var availableSlidingSyncVersionsClosure: (() async -> [SlidingSyncVersion])? + var canDeactivateAccount: Bool { + get { return underlyingCanDeactivateAccount } + set(value) { underlyingCanDeactivateAccount = value } + } + var underlyingCanDeactivateAccount: Bool! var userIDServerName: String? var userDisplayNamePublisher: CurrentValuePublisher { get { return underlyingUserDisplayNamePublisher } @@ -1943,6 +1970,11 @@ class ClientProxyMock: ClientProxyProtocol { var underlyingIgnoredUsersPublisher: CurrentValuePublisher<[String]?, Never>! var pusherNotificationClientIdentifier: String? var roomSummaryProvider: RoomSummaryProviderProtocol? + var roomsToAwait: Set { + get { return underlyingRoomsToAwait } + set(value) { underlyingRoomsToAwait = value } + } + var underlyingRoomsToAwait: Set! var alternateRoomSummaryProvider: RoomSummaryProviderProtocol? var notificationSettings: NotificationSettingsProxyProtocol { get { return underlyingNotificationSettings } @@ -2681,13 +2713,13 @@ class ClientProxyMock: ClientProxyProtocol { var roomForIdentifierReceivedIdentifier: String? var roomForIdentifierReceivedInvocations: [String] = [] - var roomForIdentifierUnderlyingReturnValue: RoomProxyProtocol? - var roomForIdentifierReturnValue: RoomProxyProtocol? { + var roomForIdentifierUnderlyingReturnValue: RoomProxyType? + var roomForIdentifierReturnValue: RoomProxyType? { get { if Thread.isMainThread { return roomForIdentifierUnderlyingReturnValue } else { - var returnValue: RoomProxyProtocol?? = nil + var returnValue: RoomProxyType?? = nil DispatchQueue.main.sync { returnValue = roomForIdentifierUnderlyingReturnValue } @@ -2705,9 +2737,9 @@ class ClientProxyMock: ClientProxyProtocol { } } } - var roomForIdentifierClosure: ((String) async -> RoomProxyProtocol?)? + var roomForIdentifierClosure: ((String) async -> RoomProxyType?)? - func roomForIdentifier(_ identifier: String) async -> RoomProxyProtocol? { + func roomForIdentifier(_ identifier: String) async -> RoomProxyType? { roomForIdentifierCallsCount += 1 roomForIdentifierReceivedIdentifier = identifier DispatchQueue.main.async { @@ -3187,6 +3219,76 @@ class ClientProxyMock: ClientProxyProtocol { return sessionVerificationControllerProxyReturnValue } } + //MARK: - deactivateAccount + + var deactivateAccountPasswordEraseDataUnderlyingCallsCount = 0 + var deactivateAccountPasswordEraseDataCallsCount: Int { + get { + if Thread.isMainThread { + return deactivateAccountPasswordEraseDataUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = deactivateAccountPasswordEraseDataUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + deactivateAccountPasswordEraseDataUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + deactivateAccountPasswordEraseDataUnderlyingCallsCount = newValue + } + } + } + } + var deactivateAccountPasswordEraseDataCalled: Bool { + return deactivateAccountPasswordEraseDataCallsCount > 0 + } + var deactivateAccountPasswordEraseDataReceivedArguments: (password: String?, eraseData: Bool)? + var deactivateAccountPasswordEraseDataReceivedInvocations: [(password: String?, eraseData: Bool)] = [] + + var deactivateAccountPasswordEraseDataUnderlyingReturnValue: Result! + var deactivateAccountPasswordEraseDataReturnValue: Result! { + get { + if Thread.isMainThread { + return deactivateAccountPasswordEraseDataUnderlyingReturnValue + } else { + var returnValue: Result? = nil + DispatchQueue.main.sync { + returnValue = deactivateAccountPasswordEraseDataUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + deactivateAccountPasswordEraseDataUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + deactivateAccountPasswordEraseDataUnderlyingReturnValue = newValue + } + } + } + } + var deactivateAccountPasswordEraseDataClosure: ((String?, Bool) async -> Result)? + + func deactivateAccount(password: String?, eraseData: Bool) async -> Result { + deactivateAccountPasswordEraseDataCallsCount += 1 + deactivateAccountPasswordEraseDataReceivedArguments = (password: password, eraseData: eraseData) + DispatchQueue.main.async { + self.deactivateAccountPasswordEraseDataReceivedInvocations.append((password: password, eraseData: eraseData)) + } + if let deactivateAccountPasswordEraseDataClosure = deactivateAccountPasswordEraseDataClosure { + return await deactivateAccountPasswordEraseDataClosure(password, eraseData) + } else { + return deactivateAccountPasswordEraseDataReturnValue + } + } //MARK: - logout var logoutUnderlyingCallsCount = 0 @@ -4894,6 +4996,11 @@ class ElementCallServiceMock: ElementCallServiceProtocol { set(value) { underlyingActions = value } } var underlyingActions: AnyPublisher! + var ongoingCallRoomIDPublisher: CurrentValuePublisher { + get { return underlyingOngoingCallRoomIDPublisher } + set(value) { underlyingOngoingCallRoomIDPublisher = value } + } + var underlyingOngoingCallRoomIDPublisher: CurrentValuePublisher! //MARK: - setClientProxy @@ -5141,17 +5248,17 @@ class ElementCallWidgetDriverMock: ElementCallWidgetDriverProtocol { return startBaseURLClientIDColorSchemeReturnValue } } - //MARK: - sendMessage + //MARK: - handleMessage - var sendMessageUnderlyingCallsCount = 0 - var sendMessageCallsCount: Int { + var handleMessageUnderlyingCallsCount = 0 + var handleMessageCallsCount: Int { get { if Thread.isMainThread { - return sendMessageUnderlyingCallsCount + return handleMessageUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = sendMessageUnderlyingCallsCount + returnValue = handleMessageUnderlyingCallsCount } return returnValue! @@ -5159,29 +5266,29 @@ class ElementCallWidgetDriverMock: ElementCallWidgetDriverProtocol { } set { if Thread.isMainThread { - sendMessageUnderlyingCallsCount = newValue + handleMessageUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - sendMessageUnderlyingCallsCount = newValue + handleMessageUnderlyingCallsCount = newValue } } } } - var sendMessageCalled: Bool { - return sendMessageCallsCount > 0 + var handleMessageCalled: Bool { + return handleMessageCallsCount > 0 } - var sendMessageReceivedMessage: String? - var sendMessageReceivedInvocations: [String] = [] + var handleMessageReceivedMessage: String? + var handleMessageReceivedInvocations: [String] = [] - var sendMessageUnderlyingReturnValue: Result! - var sendMessageReturnValue: Result! { + var handleMessageUnderlyingReturnValue: Result! + var handleMessageReturnValue: Result! { get { if Thread.isMainThread { - return sendMessageUnderlyingReturnValue + return handleMessageUnderlyingReturnValue } else { var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = sendMessageUnderlyingReturnValue + returnValue = handleMessageUnderlyingReturnValue } return returnValue! @@ -5189,83 +5296,103 @@ class ElementCallWidgetDriverMock: ElementCallWidgetDriverProtocol { } set { if Thread.isMainThread { - sendMessageUnderlyingReturnValue = newValue + handleMessageUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - sendMessageUnderlyingReturnValue = newValue + handleMessageUnderlyingReturnValue = newValue } } } } - var sendMessageClosure: ((String) async -> Result)? + var handleMessageClosure: ((String) async -> Result)? - func sendMessage(_ message: String) async -> Result { - sendMessageCallsCount += 1 - sendMessageReceivedMessage = message + func handleMessage(_ message: String) async -> Result { + handleMessageCallsCount += 1 + handleMessageReceivedMessage = message DispatchQueue.main.async { - self.sendMessageReceivedInvocations.append(message) + self.handleMessageReceivedInvocations.append(message) } - if let sendMessageClosure = sendMessageClosure { - return await sendMessageClosure(message) + if let handleMessageClosure = handleMessageClosure { + return await handleMessageClosure(message) } else { - return sendMessageReturnValue + return handleMessageReturnValue } } } -class KeychainControllerMock: KeychainControllerProtocol { - - //MARK: - setRestorationToken - - var setRestorationTokenForUsernameUnderlyingCallsCount = 0 - var setRestorationTokenForUsernameCallsCount: Int { - get { - if Thread.isMainThread { - return setRestorationTokenForUsernameUnderlyingCallsCount - } else { - var returnValue: Int? = nil - DispatchQueue.main.sync { - returnValue = setRestorationTokenForUsernameUnderlyingCallsCount - } +class InvitedRoomProxyMock: InvitedRoomProxyProtocol { + var inviterCallsCount = 0 + var inviterCalled: Bool { + return inviterCallsCount > 0 + } - return returnValue! - } - } - set { - if Thread.isMainThread { - setRestorationTokenForUsernameUnderlyingCallsCount = newValue + var inviter: RoomMemberProxyProtocol? { + get async { + inviterCallsCount += 1 + if let inviterClosure = inviterClosure { + return await inviterClosure() } else { - DispatchQueue.main.sync { - setRestorationTokenForUsernameUnderlyingCallsCount = newValue - } + return underlyingInviter } } } - var setRestorationTokenForUsernameCalled: Bool { - return setRestorationTokenForUsernameCallsCount > 0 + var underlyingInviter: RoomMemberProxyProtocol? + var inviterClosure: (() async -> RoomMemberProxyProtocol?)? + var id: String { + get { return underlyingId } + set(value) { underlyingId = value } } - var setRestorationTokenForUsernameReceivedArguments: (restorationToken: RestorationToken, forUsername: String)? - var setRestorationTokenForUsernameReceivedInvocations: [(restorationToken: RestorationToken, forUsername: String)] = [] - var setRestorationTokenForUsernameClosure: ((RestorationToken, String) -> Void)? - - func setRestorationToken(_ restorationToken: RestorationToken, forUsername: String) { - setRestorationTokenForUsernameCallsCount += 1 - setRestorationTokenForUsernameReceivedArguments = (restorationToken: restorationToken, forUsername: forUsername) - DispatchQueue.main.async { - self.setRestorationTokenForUsernameReceivedInvocations.append((restorationToken: restorationToken, forUsername: forUsername)) - } - setRestorationTokenForUsernameClosure?(restorationToken, forUsername) + var underlyingId: String! + var canonicalAlias: String? + var ownUserID: String { + get { return underlyingOwnUserID } + set(value) { underlyingOwnUserID = value } } - //MARK: - restorationTokens + var underlyingOwnUserID: String! + var name: String? + var topic: String? + var avatar: RoomAvatar { + get { return underlyingAvatar } + set(value) { underlyingAvatar = value } + } + var underlyingAvatar: RoomAvatar! + var avatarURL: URL? + var isPublic: Bool { + get { return underlyingIsPublic } + set(value) { underlyingIsPublic = value } + } + var underlyingIsPublic: Bool! + var isDirect: Bool { + get { return underlyingIsDirect } + set(value) { underlyingIsDirect = value } + } + var underlyingIsDirect: Bool! + var isSpace: Bool { + get { return underlyingIsSpace } + set(value) { underlyingIsSpace = value } + } + var underlyingIsSpace: Bool! + var joinedMembersCount: Int { + get { return underlyingJoinedMembersCount } + set(value) { underlyingJoinedMembersCount = value } + } + var underlyingJoinedMembersCount: Int! + var activeMembersCount: Int { + get { return underlyingActiveMembersCount } + set(value) { underlyingActiveMembersCount = value } + } + var underlyingActiveMembersCount: Int! - var restorationTokensUnderlyingCallsCount = 0 - var restorationTokensCallsCount: Int { + //MARK: - rejectInvitation + + var rejectInvitationUnderlyingCallsCount = 0 + var rejectInvitationCallsCount: Int { get { if Thread.isMainThread { - return restorationTokensUnderlyingCallsCount + return rejectInvitationUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = restorationTokensUnderlyingCallsCount + returnValue = rejectInvitationUnderlyingCallsCount } return returnValue! @@ -5273,27 +5400,27 @@ class KeychainControllerMock: KeychainControllerProtocol { } set { if Thread.isMainThread { - restorationTokensUnderlyingCallsCount = newValue + rejectInvitationUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - restorationTokensUnderlyingCallsCount = newValue + rejectInvitationUnderlyingCallsCount = newValue } } } } - var restorationTokensCalled: Bool { - return restorationTokensCallsCount > 0 + var rejectInvitationCalled: Bool { + return rejectInvitationCallsCount > 0 } - var restorationTokensUnderlyingReturnValue: [KeychainCredentials]! - var restorationTokensReturnValue: [KeychainCredentials]! { + var rejectInvitationUnderlyingReturnValue: Result! + var rejectInvitationReturnValue: Result! { get { if Thread.isMainThread { - return restorationTokensUnderlyingReturnValue + return rejectInvitationUnderlyingReturnValue } else { - var returnValue: [KeychainCredentials]? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = restorationTokensUnderlyingReturnValue + returnValue = rejectInvitationUnderlyingReturnValue } return returnValue! @@ -5301,35 +5428,35 @@ class KeychainControllerMock: KeychainControllerProtocol { } set { if Thread.isMainThread { - restorationTokensUnderlyingReturnValue = newValue + rejectInvitationUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - restorationTokensUnderlyingReturnValue = newValue + rejectInvitationUnderlyingReturnValue = newValue } } } } - var restorationTokensClosure: (() -> [KeychainCredentials])? + var rejectInvitationClosure: (() async -> Result)? - func restorationTokens() -> [KeychainCredentials] { - restorationTokensCallsCount += 1 - if let restorationTokensClosure = restorationTokensClosure { - return restorationTokensClosure() + func rejectInvitation() async -> Result { + rejectInvitationCallsCount += 1 + if let rejectInvitationClosure = rejectInvitationClosure { + return await rejectInvitationClosure() } else { - return restorationTokensReturnValue + return rejectInvitationReturnValue } } - //MARK: - removeRestorationTokenForUsername + //MARK: - acceptInvitation - var removeRestorationTokenForUsernameUnderlyingCallsCount = 0 - var removeRestorationTokenForUsernameCallsCount: Int { + var acceptInvitationUnderlyingCallsCount = 0 + var acceptInvitationCallsCount: Int { get { if Thread.isMainThread { - return removeRestorationTokenForUsernameUnderlyingCallsCount + return acceptInvitationUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = removeRestorationTokenForUsernameUnderlyingCallsCount + returnValue = acceptInvitationUnderlyingCallsCount } return returnValue! @@ -5337,40 +5464,27 @@ class KeychainControllerMock: KeychainControllerProtocol { } set { if Thread.isMainThread { - removeRestorationTokenForUsernameUnderlyingCallsCount = newValue + acceptInvitationUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - removeRestorationTokenForUsernameUnderlyingCallsCount = newValue + acceptInvitationUnderlyingCallsCount = newValue } } } } - var removeRestorationTokenForUsernameCalled: Bool { - return removeRestorationTokenForUsernameCallsCount > 0 - } - var removeRestorationTokenForUsernameReceivedUsername: String? - var removeRestorationTokenForUsernameReceivedInvocations: [String] = [] - var removeRestorationTokenForUsernameClosure: ((String) -> Void)? - - func removeRestorationTokenForUsername(_ username: String) { - removeRestorationTokenForUsernameCallsCount += 1 - removeRestorationTokenForUsernameReceivedUsername = username - DispatchQueue.main.async { - self.removeRestorationTokenForUsernameReceivedInvocations.append(username) - } - removeRestorationTokenForUsernameClosure?(username) + var acceptInvitationCalled: Bool { + return acceptInvitationCallsCount > 0 } - //MARK: - removeAllRestorationTokens - var removeAllRestorationTokensUnderlyingCallsCount = 0 - var removeAllRestorationTokensCallsCount: Int { + var acceptInvitationUnderlyingReturnValue: Result! + var acceptInvitationReturnValue: Result! { get { if Thread.isMainThread { - return removeAllRestorationTokensUnderlyingCallsCount + return acceptInvitationUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = removeAllRestorationTokensUnderlyingCallsCount + returnValue = acceptInvitationUnderlyingReturnValue } return returnValue! @@ -5378,63 +5492,164 @@ class KeychainControllerMock: KeychainControllerProtocol { } set { if Thread.isMainThread { - removeAllRestorationTokensUnderlyingCallsCount = newValue + acceptInvitationUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - removeAllRestorationTokensUnderlyingCallsCount = newValue + acceptInvitationUnderlyingReturnValue = newValue } } } } - var removeAllRestorationTokensCalled: Bool { - return removeAllRestorationTokensCallsCount > 0 - } - var removeAllRestorationTokensClosure: (() -> Void)? + var acceptInvitationClosure: (() async -> Result)? - func removeAllRestorationTokens() { - removeAllRestorationTokensCallsCount += 1 - removeAllRestorationTokensClosure?() + func acceptInvitation() async -> Result { + acceptInvitationCallsCount += 1 + if let acceptInvitationClosure = acceptInvitationClosure { + return await acceptInvitationClosure() + } else { + return acceptInvitationReturnValue + } } - //MARK: - containsPINCode - - var containsPINCodeThrowableError: Error? - var containsPINCodeUnderlyingCallsCount = 0 - var containsPINCodeCallsCount: Int { - get { - if Thread.isMainThread { - return containsPINCodeUnderlyingCallsCount +} +class JoinedRoomProxyMock: JoinedRoomProxyProtocol { + var isEncrypted: Bool { + get { return underlyingIsEncrypted } + set(value) { underlyingIsEncrypted = value } + } + var underlyingIsEncrypted: Bool! + var isFavouriteCallsCount = 0 + var isFavouriteCalled: Bool { + return isFavouriteCallsCount > 0 + } + + var isFavourite: Bool { + get async { + isFavouriteCallsCount += 1 + if let isFavouriteClosure = isFavouriteClosure { + return await isFavouriteClosure() } else { - var returnValue: Int? = nil - DispatchQueue.main.sync { - returnValue = containsPINCodeUnderlyingCallsCount - } + return underlyingIsFavourite + } + } + } + var underlyingIsFavourite: Bool! + var isFavouriteClosure: (() async -> Bool)? + var pinnedEventIDsCallsCount = 0 + var pinnedEventIDsCalled: Bool { + return pinnedEventIDsCallsCount > 0 + } - return returnValue! + var pinnedEventIDs: Set { + get async { + pinnedEventIDsCallsCount += 1 + if let pinnedEventIDsClosure = pinnedEventIDsClosure { + return await pinnedEventIDsClosure() + } else { + return underlyingPinnedEventIDs } } - set { - if Thread.isMainThread { - containsPINCodeUnderlyingCallsCount = newValue + } + var underlyingPinnedEventIDs: Set! + var pinnedEventIDsClosure: (() async -> Set)? + var hasOngoingCall: Bool { + get { return underlyingHasOngoingCall } + set(value) { underlyingHasOngoingCall = value } + } + var underlyingHasOngoingCall: Bool! + var activeRoomCallParticipants: [String] = [] + var membersPublisher: CurrentValuePublisher<[RoomMemberProxyProtocol], Never> { + get { return underlyingMembersPublisher } + set(value) { underlyingMembersPublisher = value } + } + var underlyingMembersPublisher: CurrentValuePublisher<[RoomMemberProxyProtocol], Never>! + var typingMembersPublisher: CurrentValuePublisher<[String], Never> { + get { return underlyingTypingMembersPublisher } + set(value) { underlyingTypingMembersPublisher = value } + } + var underlyingTypingMembersPublisher: CurrentValuePublisher<[String], Never>! + var actionsPublisher: AnyPublisher { + get { return underlyingActionsPublisher } + set(value) { underlyingActionsPublisher = value } + } + var underlyingActionsPublisher: AnyPublisher! + var timeline: TimelineProxyProtocol { + get { return underlyingTimeline } + set(value) { underlyingTimeline = value } + } + var underlyingTimeline: TimelineProxyProtocol! + var pinnedEventsTimelineCallsCount = 0 + var pinnedEventsTimelineCalled: Bool { + return pinnedEventsTimelineCallsCount > 0 + } + + var pinnedEventsTimeline: TimelineProxyProtocol? { + get async { + pinnedEventsTimelineCallsCount += 1 + if let pinnedEventsTimelineClosure = pinnedEventsTimelineClosure { + return await pinnedEventsTimelineClosure() } else { - DispatchQueue.main.sync { - containsPINCodeUnderlyingCallsCount = newValue - } + return underlyingPinnedEventsTimeline } } } - var containsPINCodeCalled: Bool { - return containsPINCodeCallsCount > 0 + var underlyingPinnedEventsTimeline: TimelineProxyProtocol? + var pinnedEventsTimelineClosure: (() async -> TimelineProxyProtocol?)? + var id: String { + get { return underlyingId } + set(value) { underlyingId = value } + } + var underlyingId: String! + var canonicalAlias: String? + var ownUserID: String { + get { return underlyingOwnUserID } + set(value) { underlyingOwnUserID = value } + } + var underlyingOwnUserID: String! + var name: String? + var topic: String? + var avatar: RoomAvatar { + get { return underlyingAvatar } + set(value) { underlyingAvatar = value } + } + var underlyingAvatar: RoomAvatar! + var avatarURL: URL? + var isPublic: Bool { + get { return underlyingIsPublic } + set(value) { underlyingIsPublic = value } + } + var underlyingIsPublic: Bool! + var isDirect: Bool { + get { return underlyingIsDirect } + set(value) { underlyingIsDirect = value } + } + var underlyingIsDirect: Bool! + var isSpace: Bool { + get { return underlyingIsSpace } + set(value) { underlyingIsSpace = value } + } + var underlyingIsSpace: Bool! + var joinedMembersCount: Int { + get { return underlyingJoinedMembersCount } + set(value) { underlyingJoinedMembersCount = value } + } + var underlyingJoinedMembersCount: Int! + var activeMembersCount: Int { + get { return underlyingActiveMembersCount } + set(value) { underlyingActiveMembersCount = value } } + var underlyingActiveMembersCount: Int! - var containsPINCodeUnderlyingReturnValue: Bool! - var containsPINCodeReturnValue: Bool! { + //MARK: - subscribeForUpdates + + var subscribeForUpdatesUnderlyingCallsCount = 0 + var subscribeForUpdatesCallsCount: Int { get { if Thread.isMainThread { - return containsPINCodeUnderlyingReturnValue + return subscribeForUpdatesUnderlyingCallsCount } else { - var returnValue: Bool? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = containsPINCodeUnderlyingReturnValue + returnValue = subscribeForUpdatesUnderlyingCallsCount } return returnValue! @@ -5442,39 +5657,34 @@ class KeychainControllerMock: KeychainControllerProtocol { } set { if Thread.isMainThread { - containsPINCodeUnderlyingReturnValue = newValue + subscribeForUpdatesUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - containsPINCodeUnderlyingReturnValue = newValue + subscribeForUpdatesUnderlyingCallsCount = newValue } } } } - var containsPINCodeClosure: (() throws -> Bool)? + var subscribeForUpdatesCalled: Bool { + return subscribeForUpdatesCallsCount > 0 + } + var subscribeForUpdatesClosure: (() async -> Void)? - func containsPINCode() throws -> Bool { - if let error = containsPINCodeThrowableError { - throw error - } - containsPINCodeCallsCount += 1 - if let containsPINCodeClosure = containsPINCodeClosure { - return try containsPINCodeClosure() - } else { - return containsPINCodeReturnValue - } + func subscribeForUpdates() async { + subscribeForUpdatesCallsCount += 1 + await subscribeForUpdatesClosure?() } - //MARK: - setPINCode + //MARK: - subscribeToRoomInfoUpdates - var setPINCodeThrowableError: Error? - var setPINCodeUnderlyingCallsCount = 0 - var setPINCodeCallsCount: Int { + var subscribeToRoomInfoUpdatesUnderlyingCallsCount = 0 + var subscribeToRoomInfoUpdatesCallsCount: Int { get { if Thread.isMainThread { - return setPINCodeUnderlyingCallsCount + return subscribeToRoomInfoUpdatesUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = setPINCodeUnderlyingCallsCount + returnValue = subscribeToRoomInfoUpdatesUnderlyingCallsCount } return returnValue! @@ -5482,43 +5692,34 @@ class KeychainControllerMock: KeychainControllerProtocol { } set { if Thread.isMainThread { - setPINCodeUnderlyingCallsCount = newValue + subscribeToRoomInfoUpdatesUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - setPINCodeUnderlyingCallsCount = newValue + subscribeToRoomInfoUpdatesUnderlyingCallsCount = newValue } } } } - var setPINCodeCalled: Bool { - return setPINCodeCallsCount > 0 + var subscribeToRoomInfoUpdatesCalled: Bool { + return subscribeToRoomInfoUpdatesCallsCount > 0 } - var setPINCodeReceivedPinCode: String? - var setPINCodeReceivedInvocations: [String] = [] - var setPINCodeClosure: ((String) throws -> Void)? + var subscribeToRoomInfoUpdatesClosure: (() -> Void)? - func setPINCode(_ pinCode: String) throws { - if let error = setPINCodeThrowableError { - throw error - } - setPINCodeCallsCount += 1 - setPINCodeReceivedPinCode = pinCode - DispatchQueue.main.async { - self.setPINCodeReceivedInvocations.append(pinCode) - } - try setPINCodeClosure?(pinCode) + func subscribeToRoomInfoUpdates() { + subscribeToRoomInfoUpdatesCallsCount += 1 + subscribeToRoomInfoUpdatesClosure?() } - //MARK: - pinCode + //MARK: - timelineFocusedOnEvent - var pinCodeUnderlyingCallsCount = 0 - var pinCodeCallsCount: Int { + var timelineFocusedOnEventEventIDNumberOfEventsUnderlyingCallsCount = 0 + var timelineFocusedOnEventEventIDNumberOfEventsCallsCount: Int { get { if Thread.isMainThread { - return pinCodeUnderlyingCallsCount + return timelineFocusedOnEventEventIDNumberOfEventsUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = pinCodeUnderlyingCallsCount + returnValue = timelineFocusedOnEventEventIDNumberOfEventsUnderlyingCallsCount } return returnValue! @@ -5526,27 +5727,29 @@ class KeychainControllerMock: KeychainControllerProtocol { } set { if Thread.isMainThread { - pinCodeUnderlyingCallsCount = newValue + timelineFocusedOnEventEventIDNumberOfEventsUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - pinCodeUnderlyingCallsCount = newValue + timelineFocusedOnEventEventIDNumberOfEventsUnderlyingCallsCount = newValue } } } } - var pinCodeCalled: Bool { - return pinCodeCallsCount > 0 + var timelineFocusedOnEventEventIDNumberOfEventsCalled: Bool { + return timelineFocusedOnEventEventIDNumberOfEventsCallsCount > 0 } + var timelineFocusedOnEventEventIDNumberOfEventsReceivedArguments: (eventID: String, numberOfEvents: UInt16)? + var timelineFocusedOnEventEventIDNumberOfEventsReceivedInvocations: [(eventID: String, numberOfEvents: UInt16)] = [] - var pinCodeUnderlyingReturnValue: String? - var pinCodeReturnValue: String? { + var timelineFocusedOnEventEventIDNumberOfEventsUnderlyingReturnValue: Result! + var timelineFocusedOnEventEventIDNumberOfEventsReturnValue: Result! { get { if Thread.isMainThread { - return pinCodeUnderlyingReturnValue + return timelineFocusedOnEventEventIDNumberOfEventsUnderlyingReturnValue } else { - var returnValue: String?? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = pinCodeUnderlyingReturnValue + returnValue = timelineFocusedOnEventEventIDNumberOfEventsUnderlyingReturnValue } return returnValue! @@ -5554,35 +5757,39 @@ class KeychainControllerMock: KeychainControllerProtocol { } set { if Thread.isMainThread { - pinCodeUnderlyingReturnValue = newValue + timelineFocusedOnEventEventIDNumberOfEventsUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - pinCodeUnderlyingReturnValue = newValue + timelineFocusedOnEventEventIDNumberOfEventsUnderlyingReturnValue = newValue } } } } - var pinCodeClosure: (() -> String?)? + var timelineFocusedOnEventEventIDNumberOfEventsClosure: ((String, UInt16) async -> Result)? - func pinCode() -> String? { - pinCodeCallsCount += 1 - if let pinCodeClosure = pinCodeClosure { - return pinCodeClosure() + func timelineFocusedOnEvent(eventID: String, numberOfEvents: UInt16) async -> Result { + timelineFocusedOnEventEventIDNumberOfEventsCallsCount += 1 + timelineFocusedOnEventEventIDNumberOfEventsReceivedArguments = (eventID: eventID, numberOfEvents: numberOfEvents) + DispatchQueue.main.async { + self.timelineFocusedOnEventEventIDNumberOfEventsReceivedInvocations.append((eventID: eventID, numberOfEvents: numberOfEvents)) + } + if let timelineFocusedOnEventEventIDNumberOfEventsClosure = timelineFocusedOnEventEventIDNumberOfEventsClosure { + return await timelineFocusedOnEventEventIDNumberOfEventsClosure(eventID, numberOfEvents) } else { - return pinCodeReturnValue + return timelineFocusedOnEventEventIDNumberOfEventsReturnValue } } - //MARK: - removePINCode + //MARK: - redact - var removePINCodeUnderlyingCallsCount = 0 - var removePINCodeCallsCount: Int { + var redactUnderlyingCallsCount = 0 + var redactCallsCount: Int { get { if Thread.isMainThread { - return removePINCodeUnderlyingCallsCount + return redactUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = removePINCodeUnderlyingCallsCount + returnValue = redactUnderlyingCallsCount } return returnValue! @@ -5590,34 +5797,29 @@ class KeychainControllerMock: KeychainControllerProtocol { } set { if Thread.isMainThread { - removePINCodeUnderlyingCallsCount = newValue + redactUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - removePINCodeUnderlyingCallsCount = newValue + redactUnderlyingCallsCount = newValue } } } } - var removePINCodeCalled: Bool { - return removePINCodeCallsCount > 0 - } - var removePINCodeClosure: (() -> Void)? - - func removePINCode() { - removePINCodeCallsCount += 1 - removePINCodeClosure?() + var redactCalled: Bool { + return redactCallsCount > 0 } - //MARK: - containsPINCodeBiometricState + var redactReceivedEventID: String? + var redactReceivedInvocations: [String] = [] - var containsPINCodeBiometricStateUnderlyingCallsCount = 0 - var containsPINCodeBiometricStateCallsCount: Int { + var redactUnderlyingReturnValue: Result! + var redactReturnValue: Result! { get { if Thread.isMainThread { - return containsPINCodeBiometricStateUnderlyingCallsCount + return redactUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = containsPINCodeBiometricStateUnderlyingCallsCount + returnValue = redactUnderlyingReturnValue } return returnValue! @@ -5625,27 +5827,39 @@ class KeychainControllerMock: KeychainControllerProtocol { } set { if Thread.isMainThread { - containsPINCodeBiometricStateUnderlyingCallsCount = newValue + redactUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - containsPINCodeBiometricStateUnderlyingCallsCount = newValue + redactUnderlyingReturnValue = newValue } } } } - var containsPINCodeBiometricStateCalled: Bool { - return containsPINCodeBiometricStateCallsCount > 0 + var redactClosure: ((String) async -> Result)? + + func redact(_ eventID: String) async -> Result { + redactCallsCount += 1 + redactReceivedEventID = eventID + DispatchQueue.main.async { + self.redactReceivedInvocations.append(eventID) + } + if let redactClosure = redactClosure { + return await redactClosure(eventID) + } else { + return redactReturnValue + } } + //MARK: - reportContent - var containsPINCodeBiometricStateUnderlyingReturnValue: Bool! - var containsPINCodeBiometricStateReturnValue: Bool! { + var reportContentReasonUnderlyingCallsCount = 0 + var reportContentReasonCallsCount: Int { get { if Thread.isMainThread { - return containsPINCodeBiometricStateUnderlyingReturnValue + return reportContentReasonUnderlyingCallsCount } else { - var returnValue: Bool? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = containsPINCodeBiometricStateUnderlyingReturnValue + returnValue = reportContentReasonUnderlyingCallsCount } return returnValue! @@ -5653,36 +5867,29 @@ class KeychainControllerMock: KeychainControllerProtocol { } set { if Thread.isMainThread { - containsPINCodeBiometricStateUnderlyingReturnValue = newValue + reportContentReasonUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - containsPINCodeBiometricStateUnderlyingReturnValue = newValue + reportContentReasonUnderlyingCallsCount = newValue } } } } - var containsPINCodeBiometricStateClosure: (() -> Bool)? - - func containsPINCodeBiometricState() -> Bool { - containsPINCodeBiometricStateCallsCount += 1 - if let containsPINCodeBiometricStateClosure = containsPINCodeBiometricStateClosure { - return containsPINCodeBiometricStateClosure() - } else { - return containsPINCodeBiometricStateReturnValue - } + var reportContentReasonCalled: Bool { + return reportContentReasonCallsCount > 0 } - //MARK: - setPINCodeBiometricState + var reportContentReasonReceivedArguments: (eventID: String, reason: String?)? + var reportContentReasonReceivedInvocations: [(eventID: String, reason: String?)] = [] - var setPINCodeBiometricStateThrowableError: Error? - var setPINCodeBiometricStateUnderlyingCallsCount = 0 - var setPINCodeBiometricStateCallsCount: Int { + var reportContentReasonUnderlyingReturnValue: Result! + var reportContentReasonReturnValue: Result! { get { if Thread.isMainThread { - return setPINCodeBiometricStateUnderlyingCallsCount + return reportContentReasonUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = setPINCodeBiometricStateUnderlyingCallsCount + returnValue = reportContentReasonUnderlyingReturnValue } return returnValue! @@ -5690,43 +5897,39 @@ class KeychainControllerMock: KeychainControllerProtocol { } set { if Thread.isMainThread { - setPINCodeBiometricStateUnderlyingCallsCount = newValue + reportContentReasonUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - setPINCodeBiometricStateUnderlyingCallsCount = newValue + reportContentReasonUnderlyingReturnValue = newValue } } } } - var setPINCodeBiometricStateCalled: Bool { - return setPINCodeBiometricStateCallsCount > 0 - } - var setPINCodeBiometricStateReceivedState: Data? - var setPINCodeBiometricStateReceivedInvocations: [Data] = [] - var setPINCodeBiometricStateClosure: ((Data) throws -> Void)? + var reportContentReasonClosure: ((String, String?) async -> Result)? - func setPINCodeBiometricState(_ state: Data) throws { - if let error = setPINCodeBiometricStateThrowableError { - throw error - } - setPINCodeBiometricStateCallsCount += 1 - setPINCodeBiometricStateReceivedState = state + func reportContent(_ eventID: String, reason: String?) async -> Result { + reportContentReasonCallsCount += 1 + reportContentReasonReceivedArguments = (eventID: eventID, reason: reason) DispatchQueue.main.async { - self.setPINCodeBiometricStateReceivedInvocations.append(state) + self.reportContentReasonReceivedInvocations.append((eventID: eventID, reason: reason)) + } + if let reportContentReasonClosure = reportContentReasonClosure { + return await reportContentReasonClosure(eventID, reason) + } else { + return reportContentReasonReturnValue } - try setPINCodeBiometricStateClosure?(state) } - //MARK: - pinCodeBiometricState + //MARK: - leaveRoom - var pinCodeBiometricStateUnderlyingCallsCount = 0 - var pinCodeBiometricStateCallsCount: Int { + var leaveRoomUnderlyingCallsCount = 0 + var leaveRoomCallsCount: Int { get { if Thread.isMainThread { - return pinCodeBiometricStateUnderlyingCallsCount + return leaveRoomUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = pinCodeBiometricStateUnderlyingCallsCount + returnValue = leaveRoomUnderlyingCallsCount } return returnValue! @@ -5734,27 +5937,27 @@ class KeychainControllerMock: KeychainControllerProtocol { } set { if Thread.isMainThread { - pinCodeBiometricStateUnderlyingCallsCount = newValue + leaveRoomUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - pinCodeBiometricStateUnderlyingCallsCount = newValue + leaveRoomUnderlyingCallsCount = newValue } } } } - var pinCodeBiometricStateCalled: Bool { - return pinCodeBiometricStateCallsCount > 0 + var leaveRoomCalled: Bool { + return leaveRoomCallsCount > 0 } - var pinCodeBiometricStateUnderlyingReturnValue: Data? - var pinCodeBiometricStateReturnValue: Data? { + var leaveRoomUnderlyingReturnValue: Result! + var leaveRoomReturnValue: Result! { get { if Thread.isMainThread { - return pinCodeBiometricStateUnderlyingReturnValue + return leaveRoomUnderlyingReturnValue } else { - var returnValue: Data?? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = pinCodeBiometricStateUnderlyingReturnValue + returnValue = leaveRoomUnderlyingReturnValue } return returnValue! @@ -5762,35 +5965,35 @@ class KeychainControllerMock: KeychainControllerProtocol { } set { if Thread.isMainThread { - pinCodeBiometricStateUnderlyingReturnValue = newValue + leaveRoomUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - pinCodeBiometricStateUnderlyingReturnValue = newValue + leaveRoomUnderlyingReturnValue = newValue } } } } - var pinCodeBiometricStateClosure: (() -> Data?)? + var leaveRoomClosure: (() async -> Result)? - func pinCodeBiometricState() -> Data? { - pinCodeBiometricStateCallsCount += 1 - if let pinCodeBiometricStateClosure = pinCodeBiometricStateClosure { - return pinCodeBiometricStateClosure() + func leaveRoom() async -> Result { + leaveRoomCallsCount += 1 + if let leaveRoomClosure = leaveRoomClosure { + return await leaveRoomClosure() } else { - return pinCodeBiometricStateReturnValue + return leaveRoomReturnValue } } - //MARK: - removePINCodeBiometricState + //MARK: - updateMembers - var removePINCodeBiometricStateUnderlyingCallsCount = 0 - var removePINCodeBiometricStateCallsCount: Int { + var updateMembersUnderlyingCallsCount = 0 + var updateMembersCallsCount: Int { get { if Thread.isMainThread { - return removePINCodeBiometricStateUnderlyingCallsCount + return updateMembersUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = removePINCodeBiometricStateUnderlyingCallsCount + returnValue = updateMembersUnderlyingCallsCount } return returnValue! @@ -5798,54 +6001,34 @@ class KeychainControllerMock: KeychainControllerProtocol { } set { if Thread.isMainThread { - removePINCodeBiometricStateUnderlyingCallsCount = newValue + updateMembersUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - removePINCodeBiometricStateUnderlyingCallsCount = newValue + updateMembersUnderlyingCallsCount = newValue } } } } - var removePINCodeBiometricStateCalled: Bool { - return removePINCodeBiometricStateCallsCount > 0 + var updateMembersCalled: Bool { + return updateMembersCallsCount > 0 } - var removePINCodeBiometricStateClosure: (() -> Void)? + var updateMembersClosure: (() async -> Void)? - func removePINCodeBiometricState() { - removePINCodeBiometricStateCallsCount += 1 - removePINCodeBiometricStateClosure?() - } -} -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 } + func updateMembers() async { + updateMembersCallsCount += 1 + await updateMembersClosure?() } - var underlyingState: MediaPlayerState! - - //MARK: - load + //MARK: - getMember - var loadMediaSourceUsingAutoplayUnderlyingCallsCount = 0 - var loadMediaSourceUsingAutoplayCallsCount: Int { + var getMemberUserIDUnderlyingCallsCount = 0 + var getMemberUserIDCallsCount: Int { get { if Thread.isMainThread { - return loadMediaSourceUsingAutoplayUnderlyingCallsCount + return getMemberUserIDUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = loadMediaSourceUsingAutoplayUnderlyingCallsCount + returnValue = getMemberUserIDUnderlyingCallsCount } return returnValue! @@ -5853,40 +6036,29 @@ class MediaPlayerMock: MediaPlayerProtocol { } set { if Thread.isMainThread { - loadMediaSourceUsingAutoplayUnderlyingCallsCount = newValue + getMemberUserIDUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - loadMediaSourceUsingAutoplayUnderlyingCallsCount = newValue + getMemberUserIDUnderlyingCallsCount = 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) + var getMemberUserIDCalled: Bool { + return getMemberUserIDCallsCount > 0 } - //MARK: - reset + var getMemberUserIDReceivedUserID: String? + var getMemberUserIDReceivedInvocations: [String] = [] - var resetUnderlyingCallsCount = 0 - var resetCallsCount: Int { + var getMemberUserIDUnderlyingReturnValue: Result! + var getMemberUserIDReturnValue: Result! { get { if Thread.isMainThread { - return resetUnderlyingCallsCount + return getMemberUserIDUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = resetUnderlyingCallsCount + returnValue = getMemberUserIDUnderlyingReturnValue } return returnValue! @@ -5894,34 +6066,39 @@ class MediaPlayerMock: MediaPlayerProtocol { } set { if Thread.isMainThread { - resetUnderlyingCallsCount = newValue + getMemberUserIDUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - resetUnderlyingCallsCount = newValue + getMemberUserIDUnderlyingReturnValue = newValue } } } } - var resetCalled: Bool { - return resetCallsCount > 0 - } - var resetClosure: (() -> Void)? + var getMemberUserIDClosure: ((String) async -> Result)? - func reset() { - resetCallsCount += 1 - resetClosure?() + func getMember(userID: String) async -> Result { + getMemberUserIDCallsCount += 1 + getMemberUserIDReceivedUserID = userID + DispatchQueue.main.async { + self.getMemberUserIDReceivedInvocations.append(userID) + } + if let getMemberUserIDClosure = getMemberUserIDClosure { + return await getMemberUserIDClosure(userID) + } else { + return getMemberUserIDReturnValue + } } - //MARK: - play + //MARK: - invite - var playUnderlyingCallsCount = 0 - var playCallsCount: Int { + var inviteUserIDUnderlyingCallsCount = 0 + var inviteUserIDCallsCount: Int { get { if Thread.isMainThread { - return playUnderlyingCallsCount + return inviteUserIDUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = playUnderlyingCallsCount + returnValue = inviteUserIDUnderlyingCallsCount } return returnValue! @@ -5929,34 +6106,29 @@ class MediaPlayerMock: MediaPlayerProtocol { } set { if Thread.isMainThread { - playUnderlyingCallsCount = newValue + inviteUserIDUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - playUnderlyingCallsCount = newValue + inviteUserIDUnderlyingCallsCount = newValue } } } } - var playCalled: Bool { - return playCallsCount > 0 - } - var playClosure: (() -> Void)? - - func play() { - playCallsCount += 1 - playClosure?() + var inviteUserIDCalled: Bool { + return inviteUserIDCallsCount > 0 } - //MARK: - pause + var inviteUserIDReceivedUserID: String? + var inviteUserIDReceivedInvocations: [String] = [] - var pauseUnderlyingCallsCount = 0 - var pauseCallsCount: Int { + var inviteUserIDUnderlyingReturnValue: Result! + var inviteUserIDReturnValue: Result! { get { if Thread.isMainThread { - return pauseUnderlyingCallsCount + return inviteUserIDUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = pauseUnderlyingCallsCount + returnValue = inviteUserIDUnderlyingReturnValue } return returnValue! @@ -5964,34 +6136,39 @@ class MediaPlayerMock: MediaPlayerProtocol { } set { if Thread.isMainThread { - pauseUnderlyingCallsCount = newValue + inviteUserIDUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - pauseUnderlyingCallsCount = newValue + inviteUserIDUnderlyingReturnValue = newValue } } } } - var pauseCalled: Bool { - return pauseCallsCount > 0 - } - var pauseClosure: (() -> Void)? + var inviteUserIDClosure: ((String) async -> Result)? - func pause() { - pauseCallsCount += 1 - pauseClosure?() + func invite(userID: String) async -> Result { + inviteUserIDCallsCount += 1 + inviteUserIDReceivedUserID = userID + DispatchQueue.main.async { + self.inviteUserIDReceivedInvocations.append(userID) + } + if let inviteUserIDClosure = inviteUserIDClosure { + return await inviteUserIDClosure(userID) + } else { + return inviteUserIDReturnValue + } } - //MARK: - stop + //MARK: - setName - var stopUnderlyingCallsCount = 0 - var stopCallsCount: Int { + var setNameUnderlyingCallsCount = 0 + var setNameCallsCount: Int { get { if Thread.isMainThread { - return stopUnderlyingCallsCount + return setNameUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = stopUnderlyingCallsCount + returnValue = setNameUnderlyingCallsCount } return returnValue! @@ -5999,34 +6176,29 @@ class MediaPlayerMock: MediaPlayerProtocol { } set { if Thread.isMainThread { - stopUnderlyingCallsCount = newValue + setNameUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - stopUnderlyingCallsCount = newValue + setNameUnderlyingCallsCount = newValue } } } } - var stopCalled: Bool { - return stopCallsCount > 0 - } - var stopClosure: (() -> Void)? - - func stop() { - stopCallsCount += 1 - stopClosure?() + var setNameCalled: Bool { + return setNameCallsCount > 0 } - //MARK: - seek + var setNameReceivedName: String? + var setNameReceivedInvocations: [String] = [] - var seekToUnderlyingCallsCount = 0 - var seekToCallsCount: Int { + var setNameUnderlyingReturnValue: Result! + var setNameReturnValue: Result! { get { if Thread.isMainThread { - return seekToUnderlyingCallsCount + return setNameUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = seekToUnderlyingCallsCount + returnValue = setNameUnderlyingReturnValue } return returnValue! @@ -6034,43 +6206,39 @@ class MediaPlayerMock: MediaPlayerProtocol { } set { if Thread.isMainThread { - seekToUnderlyingCallsCount = newValue + setNameUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - seekToUnderlyingCallsCount = newValue + setNameUnderlyingReturnValue = newValue } } } } - var seekToCalled: Bool { - return seekToCallsCount > 0 - } - var seekToReceivedProgress: Double? - var seekToReceivedInvocations: [Double] = [] - var seekToClosure: ((Double) async -> Void)? + var setNameClosure: ((String) async -> Result)? - func seek(to progress: Double) async { - seekToCallsCount += 1 - seekToReceivedProgress = progress + func setName(_ name: String) async -> Result { + setNameCallsCount += 1 + setNameReceivedName = name DispatchQueue.main.async { - self.seekToReceivedInvocations.append(progress) + self.setNameReceivedInvocations.append(name) + } + if let setNameClosure = setNameClosure { + return await setNameClosure(name) + } else { + return setNameReturnValue } - await seekToClosure?(progress) } -} -class MediaPlayerProviderMock: MediaPlayerProviderProtocol { - - //MARK: - player + //MARK: - setTopic - var playerForUnderlyingCallsCount = 0 - var playerForCallsCount: Int { + var setTopicUnderlyingCallsCount = 0 + var setTopicCallsCount: Int { get { if Thread.isMainThread { - return playerForUnderlyingCallsCount + return setTopicUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = playerForUnderlyingCallsCount + returnValue = setTopicUnderlyingCallsCount } return returnValue! @@ -6078,29 +6246,29 @@ class MediaPlayerProviderMock: MediaPlayerProviderProtocol { } set { if Thread.isMainThread { - playerForUnderlyingCallsCount = newValue + setTopicUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - playerForUnderlyingCallsCount = newValue + setTopicUnderlyingCallsCount = newValue } } } } - var playerForCalled: Bool { - return playerForCallsCount > 0 + var setTopicCalled: Bool { + return setTopicCallsCount > 0 } - var playerForReceivedMediaSource: MediaSourceProxy? - var playerForReceivedInvocations: [MediaSourceProxy] = [] + var setTopicReceivedTopic: String? + var setTopicReceivedInvocations: [String] = [] - var playerForUnderlyingReturnValue: Result! - var playerForReturnValue: Result! { + var setTopicUnderlyingReturnValue: Result! + var setTopicReturnValue: Result! { get { if Thread.isMainThread { - return playerForUnderlyingReturnValue + return setTopicUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = playerForUnderlyingReturnValue + returnValue = setTopicUnderlyingReturnValue } return returnValue! @@ -6108,39 +6276,39 @@ class MediaPlayerProviderMock: MediaPlayerProviderProtocol { } set { if Thread.isMainThread { - playerForUnderlyingReturnValue = newValue + setTopicUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - playerForUnderlyingReturnValue = newValue + setTopicUnderlyingReturnValue = newValue } } } } - var playerForClosure: ((MediaSourceProxy) -> Result)? + var setTopicClosure: ((String) async -> Result)? - func player(for mediaSource: MediaSourceProxy) -> Result { - playerForCallsCount += 1 - playerForReceivedMediaSource = mediaSource + func setTopic(_ topic: String) async -> Result { + setTopicCallsCount += 1 + setTopicReceivedTopic = topic DispatchQueue.main.async { - self.playerForReceivedInvocations.append(mediaSource) + self.setTopicReceivedInvocations.append(topic) } - if let playerForClosure = playerForClosure { - return playerForClosure(mediaSource) + if let setTopicClosure = setTopicClosure { + return await setTopicClosure(topic) } else { - return playerForReturnValue + return setTopicReturnValue } } - //MARK: - playerState + //MARK: - removeAvatar - var playerStateForUnderlyingCallsCount = 0 - var playerStateForCallsCount: Int { + var removeAvatarUnderlyingCallsCount = 0 + var removeAvatarCallsCount: Int { get { if Thread.isMainThread { - return playerStateForUnderlyingCallsCount + return removeAvatarUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = playerStateForUnderlyingCallsCount + returnValue = removeAvatarUnderlyingCallsCount } return returnValue! @@ -6148,29 +6316,27 @@ class MediaPlayerProviderMock: MediaPlayerProviderProtocol { } set { if Thread.isMainThread { - playerStateForUnderlyingCallsCount = newValue + removeAvatarUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - playerStateForUnderlyingCallsCount = newValue + removeAvatarUnderlyingCallsCount = newValue } } } } - var playerStateForCalled: Bool { - return playerStateForCallsCount > 0 + var removeAvatarCalled: Bool { + return removeAvatarCallsCount > 0 } - var playerStateForReceivedId: AudioPlayerStateIdentifier? - var playerStateForReceivedInvocations: [AudioPlayerStateIdentifier] = [] - var playerStateForUnderlyingReturnValue: AudioPlayerState? - var playerStateForReturnValue: AudioPlayerState? { + var removeAvatarUnderlyingReturnValue: Result! + var removeAvatarReturnValue: Result! { get { if Thread.isMainThread { - return playerStateForUnderlyingReturnValue + return removeAvatarUnderlyingReturnValue } else { - var returnValue: AudioPlayerState?? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = playerStateForUnderlyingReturnValue + returnValue = removeAvatarUnderlyingReturnValue } return returnValue! @@ -6178,39 +6344,35 @@ class MediaPlayerProviderMock: MediaPlayerProviderProtocol { } set { if Thread.isMainThread { - playerStateForUnderlyingReturnValue = newValue + removeAvatarUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - playerStateForUnderlyingReturnValue = newValue + removeAvatarUnderlyingReturnValue = newValue } } } } - var playerStateForClosure: ((AudioPlayerStateIdentifier) -> AudioPlayerState?)? + var removeAvatarClosure: (() async -> Result)? - func playerState(for id: AudioPlayerStateIdentifier) -> AudioPlayerState? { - playerStateForCallsCount += 1 - playerStateForReceivedId = id - DispatchQueue.main.async { - self.playerStateForReceivedInvocations.append(id) - } - if let playerStateForClosure = playerStateForClosure { - return playerStateForClosure(id) + func removeAvatar() async -> Result { + removeAvatarCallsCount += 1 + if let removeAvatarClosure = removeAvatarClosure { + return await removeAvatarClosure() } else { - return playerStateForReturnValue + return removeAvatarReturnValue } } - //MARK: - register + //MARK: - uploadAvatar - var registerAudioPlayerStateUnderlyingCallsCount = 0 - var registerAudioPlayerStateCallsCount: Int { + var uploadAvatarMediaUnderlyingCallsCount = 0 + var uploadAvatarMediaCallsCount: Int { get { if Thread.isMainThread { - return registerAudioPlayerStateUnderlyingCallsCount + return uploadAvatarMediaUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = registerAudioPlayerStateUnderlyingCallsCount + returnValue = uploadAvatarMediaUnderlyingCallsCount } return returnValue! @@ -6218,40 +6380,29 @@ class MediaPlayerProviderMock: MediaPlayerProviderProtocol { } set { if Thread.isMainThread { - registerAudioPlayerStateUnderlyingCallsCount = newValue + uploadAvatarMediaUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - registerAudioPlayerStateUnderlyingCallsCount = newValue + uploadAvatarMediaUnderlyingCallsCount = newValue } } } } - var registerAudioPlayerStateCalled: Bool { - return registerAudioPlayerStateCallsCount > 0 - } - var registerAudioPlayerStateReceivedAudioPlayerState: AudioPlayerState? - var registerAudioPlayerStateReceivedInvocations: [AudioPlayerState] = [] - var registerAudioPlayerStateClosure: ((AudioPlayerState) -> Void)? - - func register(audioPlayerState: AudioPlayerState) { - registerAudioPlayerStateCallsCount += 1 - registerAudioPlayerStateReceivedAudioPlayerState = audioPlayerState - DispatchQueue.main.async { - self.registerAudioPlayerStateReceivedInvocations.append(audioPlayerState) - } - registerAudioPlayerStateClosure?(audioPlayerState) + var uploadAvatarMediaCalled: Bool { + return uploadAvatarMediaCallsCount > 0 } - //MARK: - unregister + var uploadAvatarMediaReceivedMedia: MediaInfo? + var uploadAvatarMediaReceivedInvocations: [MediaInfo] = [] - var unregisterAudioPlayerStateUnderlyingCallsCount = 0 - var unregisterAudioPlayerStateCallsCount: Int { + var uploadAvatarMediaUnderlyingReturnValue: Result! + var uploadAvatarMediaReturnValue: Result! { get { if Thread.isMainThread { - return unregisterAudioPlayerStateUnderlyingCallsCount + return uploadAvatarMediaUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = unregisterAudioPlayerStateUnderlyingCallsCount + returnValue = uploadAvatarMediaUnderlyingReturnValue } return returnValue! @@ -6259,40 +6410,39 @@ class MediaPlayerProviderMock: MediaPlayerProviderProtocol { } set { if Thread.isMainThread { - unregisterAudioPlayerStateUnderlyingCallsCount = newValue + uploadAvatarMediaUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - unregisterAudioPlayerStateUnderlyingCallsCount = newValue + uploadAvatarMediaUnderlyingReturnValue = newValue } } } } - var unregisterAudioPlayerStateCalled: Bool { - return unregisterAudioPlayerStateCallsCount > 0 - } - var unregisterAudioPlayerStateReceivedAudioPlayerState: AudioPlayerState? - var unregisterAudioPlayerStateReceivedInvocations: [AudioPlayerState] = [] - var unregisterAudioPlayerStateClosure: ((AudioPlayerState) -> Void)? + var uploadAvatarMediaClosure: ((MediaInfo) async -> Result)? - func unregister(audioPlayerState: AudioPlayerState) { - unregisterAudioPlayerStateCallsCount += 1 - unregisterAudioPlayerStateReceivedAudioPlayerState = audioPlayerState + func uploadAvatar(media: MediaInfo) async -> Result { + uploadAvatarMediaCallsCount += 1 + uploadAvatarMediaReceivedMedia = media DispatchQueue.main.async { - self.unregisterAudioPlayerStateReceivedInvocations.append(audioPlayerState) + self.uploadAvatarMediaReceivedInvocations.append(media) + } + if let uploadAvatarMediaClosure = uploadAvatarMediaClosure { + return await uploadAvatarMediaClosure(media) + } else { + return uploadAvatarMediaReturnValue } - unregisterAudioPlayerStateClosure?(audioPlayerState) } - //MARK: - detachAllStates + //MARK: - markAsRead - var detachAllStatesExceptUnderlyingCallsCount = 0 - var detachAllStatesExceptCallsCount: Int { + var markAsReadReceiptTypeUnderlyingCallsCount = 0 + var markAsReadReceiptTypeCallsCount: Int { get { if Thread.isMainThread { - return detachAllStatesExceptUnderlyingCallsCount + return markAsReadReceiptTypeUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = detachAllStatesExceptUnderlyingCallsCount + returnValue = markAsReadReceiptTypeUnderlyingCallsCount } return returnValue! @@ -6300,52 +6450,29 @@ class MediaPlayerProviderMock: MediaPlayerProviderProtocol { } set { if Thread.isMainThread { - detachAllStatesExceptUnderlyingCallsCount = newValue + markAsReadReceiptTypeUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - detachAllStatesExceptUnderlyingCallsCount = newValue + markAsReadReceiptTypeUnderlyingCallsCount = newValue } } } } - var detachAllStatesExceptCalled: Bool { - return detachAllStatesExceptCallsCount > 0 - } - var detachAllStatesExceptReceivedException: AudioPlayerState? - var detachAllStatesExceptReceivedInvocations: [AudioPlayerState?] = [] - var detachAllStatesExceptClosure: ((AudioPlayerState?) async -> Void)? - - func detachAllStates(except exception: AudioPlayerState?) async { - detachAllStatesExceptCallsCount += 1 - detachAllStatesExceptReceivedException = exception - DispatchQueue.main.async { - self.detachAllStatesExceptReceivedInvocations.append(exception) - } - await detachAllStatesExceptClosure?(exception) - } -} -class NetworkMonitorMock: NetworkMonitorProtocol { - var reachabilityPublisher: CurrentValuePublisher { - get { return underlyingReachabilityPublisher } - set(value) { underlyingReachabilityPublisher = value } + var markAsReadReceiptTypeCalled: Bool { + return markAsReadReceiptTypeCallsCount > 0 } - var underlyingReachabilityPublisher: CurrentValuePublisher! - -} -class NotificationManagerMock: NotificationManagerProtocol { - weak var delegate: NotificationManagerDelegate? - - //MARK: - start + var markAsReadReceiptTypeReceivedReceiptType: ReceiptType? + var markAsReadReceiptTypeReceivedInvocations: [ReceiptType] = [] - var startUnderlyingCallsCount = 0 - var startCallsCount: Int { + var markAsReadReceiptTypeUnderlyingReturnValue: Result! + var markAsReadReceiptTypeReturnValue: Result! { get { if Thread.isMainThread { - return startUnderlyingCallsCount + return markAsReadReceiptTypeUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = startUnderlyingCallsCount + returnValue = markAsReadReceiptTypeUnderlyingReturnValue } return returnValue! @@ -6353,34 +6480,39 @@ class NotificationManagerMock: NotificationManagerProtocol { } set { if Thread.isMainThread { - startUnderlyingCallsCount = newValue + markAsReadReceiptTypeUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - startUnderlyingCallsCount = newValue + markAsReadReceiptTypeUnderlyingReturnValue = newValue } } } } - var startCalled: Bool { - return startCallsCount > 0 - } - var startClosure: (() -> Void)? + var markAsReadReceiptTypeClosure: ((ReceiptType) async -> Result)? - func start() { - startCallsCount += 1 - startClosure?() + func markAsRead(receiptType: ReceiptType) async -> Result { + markAsReadReceiptTypeCallsCount += 1 + markAsReadReceiptTypeReceivedReceiptType = receiptType + DispatchQueue.main.async { + self.markAsReadReceiptTypeReceivedInvocations.append(receiptType) + } + if let markAsReadReceiptTypeClosure = markAsReadReceiptTypeClosure { + return await markAsReadReceiptTypeClosure(receiptType) + } else { + return markAsReadReceiptTypeReturnValue + } } - //MARK: - register + //MARK: - edit - var registerWithUnderlyingCallsCount = 0 - var registerWithCallsCount: Int { + var editEventIDNewContentUnderlyingCallsCount = 0 + var editEventIDNewContentCallsCount: Int { get { if Thread.isMainThread { - return registerWithUnderlyingCallsCount + return editEventIDNewContentUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = registerWithUnderlyingCallsCount + returnValue = editEventIDNewContentUnderlyingCallsCount } return returnValue! @@ -6388,29 +6520,29 @@ class NotificationManagerMock: NotificationManagerProtocol { } set { if Thread.isMainThread { - registerWithUnderlyingCallsCount = newValue + editEventIDNewContentUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - registerWithUnderlyingCallsCount = newValue + editEventIDNewContentUnderlyingCallsCount = newValue } } } } - var registerWithCalled: Bool { - return registerWithCallsCount > 0 + var editEventIDNewContentCalled: Bool { + return editEventIDNewContentCallsCount > 0 } - var registerWithReceivedDeviceToken: Data? - var registerWithReceivedInvocations: [Data] = [] + var editEventIDNewContentReceivedArguments: (eventID: String, newContent: RoomMessageEventContentWithoutRelation)? + var editEventIDNewContentReceivedInvocations: [(eventID: String, newContent: RoomMessageEventContentWithoutRelation)] = [] - var registerWithUnderlyingReturnValue: Bool! - var registerWithReturnValue: Bool! { + var editEventIDNewContentUnderlyingReturnValue: Result! + var editEventIDNewContentReturnValue: Result! { get { if Thread.isMainThread { - return registerWithUnderlyingReturnValue + return editEventIDNewContentUnderlyingReturnValue } else { - var returnValue: Bool? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = registerWithUnderlyingReturnValue + returnValue = editEventIDNewContentUnderlyingReturnValue } return returnValue! @@ -6418,39 +6550,39 @@ class NotificationManagerMock: NotificationManagerProtocol { } set { if Thread.isMainThread { - registerWithUnderlyingReturnValue = newValue + editEventIDNewContentUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - registerWithUnderlyingReturnValue = newValue + editEventIDNewContentUnderlyingReturnValue = newValue } } } } - var registerWithClosure: ((Data) async -> Bool)? + var editEventIDNewContentClosure: ((String, RoomMessageEventContentWithoutRelation) async -> Result)? - func register(with deviceToken: Data) async -> Bool { - registerWithCallsCount += 1 - registerWithReceivedDeviceToken = deviceToken + func edit(eventID: String, newContent: RoomMessageEventContentWithoutRelation) async -> Result { + editEventIDNewContentCallsCount += 1 + editEventIDNewContentReceivedArguments = (eventID: eventID, newContent: newContent) DispatchQueue.main.async { - self.registerWithReceivedInvocations.append(deviceToken) + self.editEventIDNewContentReceivedInvocations.append((eventID: eventID, newContent: newContent)) } - if let registerWithClosure = registerWithClosure { - return await registerWithClosure(deviceToken) + if let editEventIDNewContentClosure = editEventIDNewContentClosure { + return await editEventIDNewContentClosure(eventID, newContent) } else { - return registerWithReturnValue + return editEventIDNewContentReturnValue } } - //MARK: - registrationFailed + //MARK: - sendTypingNotification - var registrationFailedWithUnderlyingCallsCount = 0 - var registrationFailedWithCallsCount: Int { + var sendTypingNotificationIsTypingUnderlyingCallsCount = 0 + var sendTypingNotificationIsTypingCallsCount: Int { get { if Thread.isMainThread { - return registrationFailedWithUnderlyingCallsCount + return sendTypingNotificationIsTypingUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = registrationFailedWithUnderlyingCallsCount + returnValue = sendTypingNotificationIsTypingUnderlyingCallsCount } return returnValue! @@ -6458,40 +6590,29 @@ class NotificationManagerMock: NotificationManagerProtocol { } set { if Thread.isMainThread { - registrationFailedWithUnderlyingCallsCount = newValue + sendTypingNotificationIsTypingUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - registrationFailedWithUnderlyingCallsCount = newValue + sendTypingNotificationIsTypingUnderlyingCallsCount = newValue } } } } - var registrationFailedWithCalled: Bool { - return registrationFailedWithCallsCount > 0 - } - var registrationFailedWithReceivedError: Error? - var registrationFailedWithReceivedInvocations: [Error] = [] - var registrationFailedWithClosure: ((Error) -> Void)? - - func registrationFailed(with error: Error) { - registrationFailedWithCallsCount += 1 - registrationFailedWithReceivedError = error - DispatchQueue.main.async { - self.registrationFailedWithReceivedInvocations.append(error) - } - registrationFailedWithClosure?(error) + var sendTypingNotificationIsTypingCalled: Bool { + return sendTypingNotificationIsTypingCallsCount > 0 } - //MARK: - showLocalNotification + var sendTypingNotificationIsTypingReceivedIsTyping: Bool? + var sendTypingNotificationIsTypingReceivedInvocations: [Bool] = [] - var showLocalNotificationWithSubtitleUnderlyingCallsCount = 0 - var showLocalNotificationWithSubtitleCallsCount: Int { + var sendTypingNotificationIsTypingUnderlyingReturnValue: Result! + var sendTypingNotificationIsTypingReturnValue: Result! { get { if Thread.isMainThread { - return showLocalNotificationWithSubtitleUnderlyingCallsCount + return sendTypingNotificationIsTypingUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = showLocalNotificationWithSubtitleUnderlyingCallsCount + returnValue = sendTypingNotificationIsTypingUnderlyingReturnValue } return returnValue! @@ -6499,40 +6620,40 @@ class NotificationManagerMock: NotificationManagerProtocol { } set { if Thread.isMainThread { - showLocalNotificationWithSubtitleUnderlyingCallsCount = newValue + sendTypingNotificationIsTypingUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - showLocalNotificationWithSubtitleUnderlyingCallsCount = newValue + sendTypingNotificationIsTypingUnderlyingReturnValue = newValue } } } } - var showLocalNotificationWithSubtitleCalled: Bool { - return showLocalNotificationWithSubtitleCallsCount > 0 - } - var showLocalNotificationWithSubtitleReceivedArguments: (title: String, subtitle: String?)? - var showLocalNotificationWithSubtitleReceivedInvocations: [(title: String, subtitle: String?)] = [] - var showLocalNotificationWithSubtitleClosure: ((String, String?) async -> Void)? + var sendTypingNotificationIsTypingClosure: ((Bool) async -> Result)? - func showLocalNotification(with title: String, subtitle: String?) async { - showLocalNotificationWithSubtitleCallsCount += 1 - showLocalNotificationWithSubtitleReceivedArguments = (title: title, subtitle: subtitle) + @discardableResult + func sendTypingNotification(isTyping: Bool) async -> Result { + sendTypingNotificationIsTypingCallsCount += 1 + sendTypingNotificationIsTypingReceivedIsTyping = isTyping DispatchQueue.main.async { - self.showLocalNotificationWithSubtitleReceivedInvocations.append((title: title, subtitle: subtitle)) + self.sendTypingNotificationIsTypingReceivedInvocations.append(isTyping) } - await showLocalNotificationWithSubtitleClosure?(title, subtitle) - } - //MARK: - setUserSession + if let sendTypingNotificationIsTypingClosure = sendTypingNotificationIsTypingClosure { + return await sendTypingNotificationIsTypingClosure(isTyping) + } else { + return sendTypingNotificationIsTypingReturnValue + } + } + //MARK: - resend - var setUserSessionUnderlyingCallsCount = 0 - var setUserSessionCallsCount: Int { + var resendItemIDUnderlyingCallsCount = 0 + var resendItemIDCallsCount: Int { get { if Thread.isMainThread { - return setUserSessionUnderlyingCallsCount + return resendItemIDUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = setUserSessionUnderlyingCallsCount + returnValue = resendItemIDUnderlyingCallsCount } return returnValue! @@ -6540,40 +6661,29 @@ class NotificationManagerMock: NotificationManagerProtocol { } set { if Thread.isMainThread { - setUserSessionUnderlyingCallsCount = newValue + resendItemIDUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - setUserSessionUnderlyingCallsCount = newValue + resendItemIDUnderlyingCallsCount = newValue } } } } - var setUserSessionCalled: Bool { - return setUserSessionCallsCount > 0 - } - var setUserSessionReceivedUserSession: UserSessionProtocol? - var setUserSessionReceivedInvocations: [UserSessionProtocol?] = [] - var setUserSessionClosure: ((UserSessionProtocol?) -> Void)? - - func setUserSession(_ userSession: UserSessionProtocol?) { - setUserSessionCallsCount += 1 - setUserSessionReceivedUserSession = userSession - DispatchQueue.main.async { - self.setUserSessionReceivedInvocations.append(userSession) - } - setUserSessionClosure?(userSession) + var resendItemIDCalled: Bool { + return resendItemIDCallsCount > 0 } - //MARK: - requestAuthorization + var resendItemIDReceivedItemID: TimelineItemIdentifier? + var resendItemIDReceivedInvocations: [TimelineItemIdentifier] = [] - var requestAuthorizationUnderlyingCallsCount = 0 - var requestAuthorizationCallsCount: Int { + var resendItemIDUnderlyingReturnValue: Result! + var resendItemIDReturnValue: Result! { get { if Thread.isMainThread { - return requestAuthorizationUnderlyingCallsCount + return resendItemIDUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = requestAuthorizationUnderlyingCallsCount + returnValue = resendItemIDUnderlyingReturnValue } return returnValue! @@ -6581,34 +6691,39 @@ class NotificationManagerMock: NotificationManagerProtocol { } set { if Thread.isMainThread { - requestAuthorizationUnderlyingCallsCount = newValue + resendItemIDUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - requestAuthorizationUnderlyingCallsCount = newValue + resendItemIDUnderlyingReturnValue = newValue } } } } - var requestAuthorizationCalled: Bool { - return requestAuthorizationCallsCount > 0 - } - var requestAuthorizationClosure: (() -> Void)? + var resendItemIDClosure: ((TimelineItemIdentifier) async -> Result)? - func requestAuthorization() { - requestAuthorizationCallsCount += 1 - requestAuthorizationClosure?() + 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: - removeDeliveredMessageNotifications + //MARK: - ignoreDeviceTrustAndResend - var removeDeliveredMessageNotificationsForUnderlyingCallsCount = 0 - var removeDeliveredMessageNotificationsForCallsCount: Int { + var ignoreDeviceTrustAndResendDevicesItemIDUnderlyingCallsCount = 0 + var ignoreDeviceTrustAndResendDevicesItemIDCallsCount: Int { get { if Thread.isMainThread { - return removeDeliveredMessageNotificationsForUnderlyingCallsCount + return ignoreDeviceTrustAndResendDevicesItemIDUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = removeDeliveredMessageNotificationsForUnderlyingCallsCount + returnValue = ignoreDeviceTrustAndResendDevicesItemIDUnderlyingCallsCount } return returnValue! @@ -6616,40 +6731,29 @@ class NotificationManagerMock: NotificationManagerProtocol { } set { if Thread.isMainThread { - removeDeliveredMessageNotificationsForUnderlyingCallsCount = newValue + ignoreDeviceTrustAndResendDevicesItemIDUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - removeDeliveredMessageNotificationsForUnderlyingCallsCount = newValue + ignoreDeviceTrustAndResendDevicesItemIDUnderlyingCallsCount = newValue } } } } - var removeDeliveredMessageNotificationsForCalled: Bool { - return removeDeliveredMessageNotificationsForCallsCount > 0 - } - var removeDeliveredMessageNotificationsForReceivedRoomID: String? - var removeDeliveredMessageNotificationsForReceivedInvocations: [String] = [] - var removeDeliveredMessageNotificationsForClosure: ((String) async -> Void)? - - func removeDeliveredMessageNotifications(for roomID: String) async { - removeDeliveredMessageNotificationsForCallsCount += 1 - removeDeliveredMessageNotificationsForReceivedRoomID = roomID - DispatchQueue.main.async { - self.removeDeliveredMessageNotificationsForReceivedInvocations.append(roomID) - } - await removeDeliveredMessageNotificationsForClosure?(roomID) + var ignoreDeviceTrustAndResendDevicesItemIDCalled: Bool { + return ignoreDeviceTrustAndResendDevicesItemIDCallsCount > 0 } - //MARK: - removeDeliveredInviteNotifications + var ignoreDeviceTrustAndResendDevicesItemIDReceivedArguments: (devices: [String: [String]], itemID: TimelineItemIdentifier)? + var ignoreDeviceTrustAndResendDevicesItemIDReceivedInvocations: [(devices: [String: [String]], itemID: TimelineItemIdentifier)] = [] - var removeDeliveredInviteNotificationsUnderlyingCallsCount = 0 - var removeDeliveredInviteNotificationsCallsCount: Int { + var ignoreDeviceTrustAndResendDevicesItemIDUnderlyingReturnValue: Result! + var ignoreDeviceTrustAndResendDevicesItemIDReturnValue: Result! { get { if Thread.isMainThread { - return removeDeliveredInviteNotificationsUnderlyingCallsCount + return ignoreDeviceTrustAndResendDevicesItemIDUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = removeDeliveredInviteNotificationsUnderlyingCallsCount + returnValue = ignoreDeviceTrustAndResendDevicesItemIDUnderlyingReturnValue } return returnValue! @@ -6657,43 +6761,39 @@ class NotificationManagerMock: NotificationManagerProtocol { } set { if Thread.isMainThread { - removeDeliveredInviteNotificationsUnderlyingCallsCount = newValue + ignoreDeviceTrustAndResendDevicesItemIDUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - removeDeliveredInviteNotificationsUnderlyingCallsCount = newValue + ignoreDeviceTrustAndResendDevicesItemIDUnderlyingReturnValue = newValue } } } } - var removeDeliveredInviteNotificationsCalled: Bool { - return removeDeliveredInviteNotificationsCallsCount > 0 - } - var removeDeliveredInviteNotificationsClosure: (() async -> Void)? + var ignoreDeviceTrustAndResendDevicesItemIDClosure: (([String: [String]], TimelineItemIdentifier) async -> Result)? - func removeDeliveredInviteNotifications() async { - removeDeliveredInviteNotificationsCallsCount += 1 - await removeDeliveredInviteNotificationsClosure?() - } -} -class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { - var callbacks: PassthroughSubject { - get { return underlyingCallbacks } - set(value) { underlyingCallbacks = value } + func ignoreDeviceTrustAndResend(devices: [String: [String]], itemID: TimelineItemIdentifier) async -> Result { + ignoreDeviceTrustAndResendDevicesItemIDCallsCount += 1 + ignoreDeviceTrustAndResendDevicesItemIDReceivedArguments = (devices: devices, itemID: itemID) + DispatchQueue.main.async { + self.ignoreDeviceTrustAndResendDevicesItemIDReceivedInvocations.append((devices: devices, itemID: itemID)) + } + if let ignoreDeviceTrustAndResendDevicesItemIDClosure = ignoreDeviceTrustAndResendDevicesItemIDClosure { + return await ignoreDeviceTrustAndResendDevicesItemIDClosure(devices, itemID) + } else { + return ignoreDeviceTrustAndResendDevicesItemIDReturnValue + } } - var underlyingCallbacks: PassthroughSubject! - - //MARK: - getNotificationSettings + //MARK: - withdrawVerificationAndResend - var getNotificationSettingsRoomIdIsEncryptedIsOneToOneThrowableError: Error? - var getNotificationSettingsRoomIdIsEncryptedIsOneToOneUnderlyingCallsCount = 0 - var getNotificationSettingsRoomIdIsEncryptedIsOneToOneCallsCount: Int { + var withdrawVerificationAndResendUserIDsItemIDUnderlyingCallsCount = 0 + var withdrawVerificationAndResendUserIDsItemIDCallsCount: Int { get { if Thread.isMainThread { - return getNotificationSettingsRoomIdIsEncryptedIsOneToOneUnderlyingCallsCount + return withdrawVerificationAndResendUserIDsItemIDUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = getNotificationSettingsRoomIdIsEncryptedIsOneToOneUnderlyingCallsCount + returnValue = withdrawVerificationAndResendUserIDsItemIDUnderlyingCallsCount } return returnValue! @@ -6701,29 +6801,29 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - getNotificationSettingsRoomIdIsEncryptedIsOneToOneUnderlyingCallsCount = newValue + withdrawVerificationAndResendUserIDsItemIDUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - getNotificationSettingsRoomIdIsEncryptedIsOneToOneUnderlyingCallsCount = newValue + withdrawVerificationAndResendUserIDsItemIDUnderlyingCallsCount = newValue } } } } - var getNotificationSettingsRoomIdIsEncryptedIsOneToOneCalled: Bool { - return getNotificationSettingsRoomIdIsEncryptedIsOneToOneCallsCount > 0 + var withdrawVerificationAndResendUserIDsItemIDCalled: Bool { + return withdrawVerificationAndResendUserIDsItemIDCallsCount > 0 } - var getNotificationSettingsRoomIdIsEncryptedIsOneToOneReceivedArguments: (roomId: String, isEncrypted: Bool, isOneToOne: Bool)? - var getNotificationSettingsRoomIdIsEncryptedIsOneToOneReceivedInvocations: [(roomId: String, isEncrypted: Bool, isOneToOne: Bool)] = [] + var withdrawVerificationAndResendUserIDsItemIDReceivedArguments: (userIDs: [String], itemID: TimelineItemIdentifier)? + var withdrawVerificationAndResendUserIDsItemIDReceivedInvocations: [(userIDs: [String], itemID: TimelineItemIdentifier)] = [] - var getNotificationSettingsRoomIdIsEncryptedIsOneToOneUnderlyingReturnValue: RoomNotificationSettingsProxyProtocol! - var getNotificationSettingsRoomIdIsEncryptedIsOneToOneReturnValue: RoomNotificationSettingsProxyProtocol! { + var withdrawVerificationAndResendUserIDsItemIDUnderlyingReturnValue: Result! + var withdrawVerificationAndResendUserIDsItemIDReturnValue: Result! { get { if Thread.isMainThread { - return getNotificationSettingsRoomIdIsEncryptedIsOneToOneUnderlyingReturnValue + return withdrawVerificationAndResendUserIDsItemIDUnderlyingReturnValue } else { - var returnValue: RoomNotificationSettingsProxyProtocol? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = getNotificationSettingsRoomIdIsEncryptedIsOneToOneUnderlyingReturnValue + returnValue = withdrawVerificationAndResendUserIDsItemIDUnderlyingReturnValue } return returnValue! @@ -6731,43 +6831,39 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - getNotificationSettingsRoomIdIsEncryptedIsOneToOneUnderlyingReturnValue = newValue + withdrawVerificationAndResendUserIDsItemIDUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - getNotificationSettingsRoomIdIsEncryptedIsOneToOneUnderlyingReturnValue = newValue + withdrawVerificationAndResendUserIDsItemIDUnderlyingReturnValue = newValue } } } } - var getNotificationSettingsRoomIdIsEncryptedIsOneToOneClosure: ((String, Bool, Bool) async throws -> RoomNotificationSettingsProxyProtocol)? + var withdrawVerificationAndResendUserIDsItemIDClosure: (([String], TimelineItemIdentifier) async -> Result)? - func getNotificationSettings(roomId: String, isEncrypted: Bool, isOneToOne: Bool) async throws -> RoomNotificationSettingsProxyProtocol { - if let error = getNotificationSettingsRoomIdIsEncryptedIsOneToOneThrowableError { - throw error - } - getNotificationSettingsRoomIdIsEncryptedIsOneToOneCallsCount += 1 - getNotificationSettingsRoomIdIsEncryptedIsOneToOneReceivedArguments = (roomId: roomId, isEncrypted: isEncrypted, isOneToOne: isOneToOne) + func withdrawVerificationAndResend(userIDs: [String], itemID: TimelineItemIdentifier) async -> Result { + withdrawVerificationAndResendUserIDsItemIDCallsCount += 1 + withdrawVerificationAndResendUserIDsItemIDReceivedArguments = (userIDs: userIDs, itemID: itemID) DispatchQueue.main.async { - self.getNotificationSettingsRoomIdIsEncryptedIsOneToOneReceivedInvocations.append((roomId: roomId, isEncrypted: isEncrypted, isOneToOne: isOneToOne)) + self.withdrawVerificationAndResendUserIDsItemIDReceivedInvocations.append((userIDs: userIDs, itemID: itemID)) } - if let getNotificationSettingsRoomIdIsEncryptedIsOneToOneClosure = getNotificationSettingsRoomIdIsEncryptedIsOneToOneClosure { - return try await getNotificationSettingsRoomIdIsEncryptedIsOneToOneClosure(roomId, isEncrypted, isOneToOne) + if let withdrawVerificationAndResendUserIDsItemIDClosure = withdrawVerificationAndResendUserIDsItemIDClosure { + return await withdrawVerificationAndResendUserIDsItemIDClosure(userIDs, itemID) } else { - return getNotificationSettingsRoomIdIsEncryptedIsOneToOneReturnValue + return withdrawVerificationAndResendUserIDsItemIDReturnValue } } - //MARK: - setNotificationMode + //MARK: - flagAsUnread - var setNotificationModeRoomIdModeThrowableError: Error? - var setNotificationModeRoomIdModeUnderlyingCallsCount = 0 - var setNotificationModeRoomIdModeCallsCount: Int { + var flagAsUnreadUnderlyingCallsCount = 0 + var flagAsUnreadCallsCount: Int { get { if Thread.isMainThread { - return setNotificationModeRoomIdModeUnderlyingCallsCount + return flagAsUnreadUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = setNotificationModeRoomIdModeUnderlyingCallsCount + returnValue = flagAsUnreadUnderlyingCallsCount } return returnValue! @@ -6775,44 +6871,29 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - setNotificationModeRoomIdModeUnderlyingCallsCount = newValue + flagAsUnreadUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - setNotificationModeRoomIdModeUnderlyingCallsCount = newValue + flagAsUnreadUnderlyingCallsCount = newValue } } } } - var setNotificationModeRoomIdModeCalled: Bool { - return setNotificationModeRoomIdModeCallsCount > 0 - } - var setNotificationModeRoomIdModeReceivedArguments: (roomId: String, mode: RoomNotificationModeProxy)? - var setNotificationModeRoomIdModeReceivedInvocations: [(roomId: String, mode: RoomNotificationModeProxy)] = [] - var setNotificationModeRoomIdModeClosure: ((String, RoomNotificationModeProxy) async throws -> Void)? - - func setNotificationMode(roomId: String, mode: RoomNotificationModeProxy) async throws { - if let error = setNotificationModeRoomIdModeThrowableError { - throw error - } - setNotificationModeRoomIdModeCallsCount += 1 - setNotificationModeRoomIdModeReceivedArguments = (roomId: roomId, mode: mode) - DispatchQueue.main.async { - self.setNotificationModeRoomIdModeReceivedInvocations.append((roomId: roomId, mode: mode)) - } - try await setNotificationModeRoomIdModeClosure?(roomId, mode) + var flagAsUnreadCalled: Bool { + return flagAsUnreadCallsCount > 0 } - //MARK: - getUserDefinedRoomNotificationMode + var flagAsUnreadReceivedIsUnread: Bool? + var flagAsUnreadReceivedInvocations: [Bool] = [] - var getUserDefinedRoomNotificationModeRoomIdThrowableError: Error? - var getUserDefinedRoomNotificationModeRoomIdUnderlyingCallsCount = 0 - var getUserDefinedRoomNotificationModeRoomIdCallsCount: Int { + var flagAsUnreadUnderlyingReturnValue: Result! + var flagAsUnreadReturnValue: Result! { get { if Thread.isMainThread { - return getUserDefinedRoomNotificationModeRoomIdUnderlyingCallsCount + return flagAsUnreadUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = getUserDefinedRoomNotificationModeRoomIdUnderlyingCallsCount + returnValue = flagAsUnreadUnderlyingReturnValue } return returnValue! @@ -6820,29 +6901,39 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - getUserDefinedRoomNotificationModeRoomIdUnderlyingCallsCount = newValue + flagAsUnreadUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - getUserDefinedRoomNotificationModeRoomIdUnderlyingCallsCount = newValue + flagAsUnreadUnderlyingReturnValue = newValue } } } } - var getUserDefinedRoomNotificationModeRoomIdCalled: Bool { - return getUserDefinedRoomNotificationModeRoomIdCallsCount > 0 + var flagAsUnreadClosure: ((Bool) async -> Result)? + + func flagAsUnread(_ isUnread: Bool) async -> Result { + flagAsUnreadCallsCount += 1 + flagAsUnreadReceivedIsUnread = isUnread + DispatchQueue.main.async { + self.flagAsUnreadReceivedInvocations.append(isUnread) + } + if let flagAsUnreadClosure = flagAsUnreadClosure { + return await flagAsUnreadClosure(isUnread) + } else { + return flagAsUnreadReturnValue + } } - var getUserDefinedRoomNotificationModeRoomIdReceivedRoomId: String? - var getUserDefinedRoomNotificationModeRoomIdReceivedInvocations: [String] = [] + //MARK: - flagAsFavourite - var getUserDefinedRoomNotificationModeRoomIdUnderlyingReturnValue: RoomNotificationModeProxy? - var getUserDefinedRoomNotificationModeRoomIdReturnValue: RoomNotificationModeProxy? { + var flagAsFavouriteUnderlyingCallsCount = 0 + var flagAsFavouriteCallsCount: Int { get { if Thread.isMainThread { - return getUserDefinedRoomNotificationModeRoomIdUnderlyingReturnValue + return flagAsFavouriteUnderlyingCallsCount } else { - var returnValue: RoomNotificationModeProxy?? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = getUserDefinedRoomNotificationModeRoomIdUnderlyingReturnValue + returnValue = flagAsFavouriteUnderlyingCallsCount } return returnValue! @@ -6850,42 +6941,29 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - getUserDefinedRoomNotificationModeRoomIdUnderlyingReturnValue = newValue + flagAsFavouriteUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - getUserDefinedRoomNotificationModeRoomIdUnderlyingReturnValue = newValue + flagAsFavouriteUnderlyingCallsCount = newValue } } } } - var getUserDefinedRoomNotificationModeRoomIdClosure: ((String) async throws -> RoomNotificationModeProxy?)? - - func getUserDefinedRoomNotificationMode(roomId: String) async throws -> RoomNotificationModeProxy? { - if let error = getUserDefinedRoomNotificationModeRoomIdThrowableError { - throw error - } - getUserDefinedRoomNotificationModeRoomIdCallsCount += 1 - getUserDefinedRoomNotificationModeRoomIdReceivedRoomId = roomId - DispatchQueue.main.async { - self.getUserDefinedRoomNotificationModeRoomIdReceivedInvocations.append(roomId) - } - if let getUserDefinedRoomNotificationModeRoomIdClosure = getUserDefinedRoomNotificationModeRoomIdClosure { - return try await getUserDefinedRoomNotificationModeRoomIdClosure(roomId) - } else { - return getUserDefinedRoomNotificationModeRoomIdReturnValue - } + var flagAsFavouriteCalled: Bool { + return flagAsFavouriteCallsCount > 0 } - //MARK: - getDefaultRoomNotificationMode + var flagAsFavouriteReceivedIsFavourite: Bool? + var flagAsFavouriteReceivedInvocations: [Bool] = [] - var getDefaultRoomNotificationModeIsEncryptedIsOneToOneUnderlyingCallsCount = 0 - var getDefaultRoomNotificationModeIsEncryptedIsOneToOneCallsCount: Int { + var flagAsFavouriteUnderlyingReturnValue: Result! + var flagAsFavouriteReturnValue: Result! { get { if Thread.isMainThread { - return getDefaultRoomNotificationModeIsEncryptedIsOneToOneUnderlyingCallsCount + return flagAsFavouriteUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = getDefaultRoomNotificationModeIsEncryptedIsOneToOneUnderlyingCallsCount + returnValue = flagAsFavouriteUnderlyingReturnValue } return returnValue! @@ -6893,29 +6971,39 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - getDefaultRoomNotificationModeIsEncryptedIsOneToOneUnderlyingCallsCount = newValue + flagAsFavouriteUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - getDefaultRoomNotificationModeIsEncryptedIsOneToOneUnderlyingCallsCount = newValue + flagAsFavouriteUnderlyingReturnValue = newValue } } } } - var getDefaultRoomNotificationModeIsEncryptedIsOneToOneCalled: Bool { - return getDefaultRoomNotificationModeIsEncryptedIsOneToOneCallsCount > 0 - } - var getDefaultRoomNotificationModeIsEncryptedIsOneToOneReceivedArguments: (isEncrypted: Bool, isOneToOne: Bool)? - var getDefaultRoomNotificationModeIsEncryptedIsOneToOneReceivedInvocations: [(isEncrypted: Bool, isOneToOne: Bool)] = [] + var flagAsFavouriteClosure: ((Bool) async -> Result)? - var getDefaultRoomNotificationModeIsEncryptedIsOneToOneUnderlyingReturnValue: RoomNotificationModeProxy! - var getDefaultRoomNotificationModeIsEncryptedIsOneToOneReturnValue: RoomNotificationModeProxy! { - get { - if Thread.isMainThread { - return getDefaultRoomNotificationModeIsEncryptedIsOneToOneUnderlyingReturnValue + func flagAsFavourite(_ isFavourite: Bool) async -> Result { + flagAsFavouriteCallsCount += 1 + flagAsFavouriteReceivedIsFavourite = isFavourite + DispatchQueue.main.async { + self.flagAsFavouriteReceivedInvocations.append(isFavourite) + } + if let flagAsFavouriteClosure = flagAsFavouriteClosure { + return await flagAsFavouriteClosure(isFavourite) + } else { + return flagAsFavouriteReturnValue + } + } + //MARK: - powerLevels + + var powerLevelsUnderlyingCallsCount = 0 + var powerLevelsCallsCount: Int { + get { + if Thread.isMainThread { + return powerLevelsUnderlyingCallsCount } else { - var returnValue: RoomNotificationModeProxy? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = getDefaultRoomNotificationModeIsEncryptedIsOneToOneUnderlyingReturnValue + returnValue = powerLevelsUnderlyingCallsCount } return returnValue! @@ -6923,40 +7011,27 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - getDefaultRoomNotificationModeIsEncryptedIsOneToOneUnderlyingReturnValue = newValue + powerLevelsUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - getDefaultRoomNotificationModeIsEncryptedIsOneToOneUnderlyingReturnValue = newValue + powerLevelsUnderlyingCallsCount = newValue } } } } - var getDefaultRoomNotificationModeIsEncryptedIsOneToOneClosure: ((Bool, Bool) async -> RoomNotificationModeProxy)? - - func getDefaultRoomNotificationMode(isEncrypted: Bool, isOneToOne: Bool) async -> RoomNotificationModeProxy { - getDefaultRoomNotificationModeIsEncryptedIsOneToOneCallsCount += 1 - getDefaultRoomNotificationModeIsEncryptedIsOneToOneReceivedArguments = (isEncrypted: isEncrypted, isOneToOne: isOneToOne) - DispatchQueue.main.async { - self.getDefaultRoomNotificationModeIsEncryptedIsOneToOneReceivedInvocations.append((isEncrypted: isEncrypted, isOneToOne: isOneToOne)) - } - if let getDefaultRoomNotificationModeIsEncryptedIsOneToOneClosure = getDefaultRoomNotificationModeIsEncryptedIsOneToOneClosure { - return await getDefaultRoomNotificationModeIsEncryptedIsOneToOneClosure(isEncrypted, isOneToOne) - } else { - return getDefaultRoomNotificationModeIsEncryptedIsOneToOneReturnValue - } + var powerLevelsCalled: Bool { + return powerLevelsCallsCount > 0 } - //MARK: - setDefaultRoomNotificationMode - var setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeThrowableError: Error? - var setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeUnderlyingCallsCount = 0 - var setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeCallsCount: Int { + var powerLevelsUnderlyingReturnValue: Result! + var powerLevelsReturnValue: Result! { get { if Thread.isMainThread { - return setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeUnderlyingCallsCount + return powerLevelsUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeUnderlyingCallsCount + returnValue = powerLevelsUnderlyingReturnValue } return returnValue! @@ -6964,44 +7039,35 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeUnderlyingCallsCount = newValue + powerLevelsUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeUnderlyingCallsCount = newValue + powerLevelsUnderlyingReturnValue = newValue } } } } - var setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeCalled: Bool { - return setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeCallsCount > 0 - } - var setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeReceivedArguments: (isEncrypted: Bool, isOneToOne: Bool, mode: RoomNotificationModeProxy)? - var setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeReceivedInvocations: [(isEncrypted: Bool, isOneToOne: Bool, mode: RoomNotificationModeProxy)] = [] - var setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeClosure: ((Bool, Bool, RoomNotificationModeProxy) async throws -> Void)? + var powerLevelsClosure: (() async -> Result)? - func setDefaultRoomNotificationMode(isEncrypted: Bool, isOneToOne: Bool, mode: RoomNotificationModeProxy) async throws { - if let error = setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeThrowableError { - throw error - } - setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeCallsCount += 1 - setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeReceivedArguments = (isEncrypted: isEncrypted, isOneToOne: isOneToOne, mode: mode) - DispatchQueue.main.async { - self.setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeReceivedInvocations.append((isEncrypted: isEncrypted, isOneToOne: isOneToOne, mode: mode)) + func powerLevels() async -> Result { + powerLevelsCallsCount += 1 + if let powerLevelsClosure = powerLevelsClosure { + return await powerLevelsClosure() + } else { + return powerLevelsReturnValue } - try await setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeClosure?(isEncrypted, isOneToOne, mode) } - //MARK: - restoreDefaultNotificationMode + //MARK: - applyPowerLevelChanges - var restoreDefaultNotificationModeRoomIdThrowableError: Error? - var restoreDefaultNotificationModeRoomIdUnderlyingCallsCount = 0 - var restoreDefaultNotificationModeRoomIdCallsCount: Int { + var applyPowerLevelChangesUnderlyingCallsCount = 0 + var applyPowerLevelChangesCallsCount: Int { get { if Thread.isMainThread { - return restoreDefaultNotificationModeRoomIdUnderlyingCallsCount + return applyPowerLevelChangesUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = restoreDefaultNotificationModeRoomIdUnderlyingCallsCount + returnValue = applyPowerLevelChangesUnderlyingCallsCount } return returnValue! @@ -7009,44 +7075,29 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - restoreDefaultNotificationModeRoomIdUnderlyingCallsCount = newValue + applyPowerLevelChangesUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - restoreDefaultNotificationModeRoomIdUnderlyingCallsCount = newValue + applyPowerLevelChangesUnderlyingCallsCount = newValue } } } } - var restoreDefaultNotificationModeRoomIdCalled: Bool { - return restoreDefaultNotificationModeRoomIdCallsCount > 0 - } - var restoreDefaultNotificationModeRoomIdReceivedRoomId: String? - var restoreDefaultNotificationModeRoomIdReceivedInvocations: [String] = [] - var restoreDefaultNotificationModeRoomIdClosure: ((String) async throws -> Void)? - - func restoreDefaultNotificationMode(roomId: String) async throws { - if let error = restoreDefaultNotificationModeRoomIdThrowableError { - throw error - } - restoreDefaultNotificationModeRoomIdCallsCount += 1 - restoreDefaultNotificationModeRoomIdReceivedRoomId = roomId - DispatchQueue.main.async { - self.restoreDefaultNotificationModeRoomIdReceivedInvocations.append(roomId) - } - try await restoreDefaultNotificationModeRoomIdClosure?(roomId) + var applyPowerLevelChangesCalled: Bool { + return applyPowerLevelChangesCallsCount > 0 } - //MARK: - unmuteRoom + var applyPowerLevelChangesReceivedChanges: RoomPowerLevelChanges? + var applyPowerLevelChangesReceivedInvocations: [RoomPowerLevelChanges] = [] - var unmuteRoomRoomIdIsEncryptedIsOneToOneThrowableError: Error? - var unmuteRoomRoomIdIsEncryptedIsOneToOneUnderlyingCallsCount = 0 - var unmuteRoomRoomIdIsEncryptedIsOneToOneCallsCount: Int { + var applyPowerLevelChangesUnderlyingReturnValue: Result! + var applyPowerLevelChangesReturnValue: Result! { get { if Thread.isMainThread { - return unmuteRoomRoomIdIsEncryptedIsOneToOneUnderlyingCallsCount + return applyPowerLevelChangesUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = unmuteRoomRoomIdIsEncryptedIsOneToOneUnderlyingCallsCount + returnValue = applyPowerLevelChangesUnderlyingReturnValue } return returnValue! @@ -7054,44 +7105,39 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - unmuteRoomRoomIdIsEncryptedIsOneToOneUnderlyingCallsCount = newValue + applyPowerLevelChangesUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - unmuteRoomRoomIdIsEncryptedIsOneToOneUnderlyingCallsCount = newValue + applyPowerLevelChangesUnderlyingReturnValue = newValue } } } } - var unmuteRoomRoomIdIsEncryptedIsOneToOneCalled: Bool { - return unmuteRoomRoomIdIsEncryptedIsOneToOneCallsCount > 0 - } - var unmuteRoomRoomIdIsEncryptedIsOneToOneReceivedArguments: (roomId: String, isEncrypted: Bool, isOneToOne: Bool)? - var unmuteRoomRoomIdIsEncryptedIsOneToOneReceivedInvocations: [(roomId: String, isEncrypted: Bool, isOneToOne: Bool)] = [] - var unmuteRoomRoomIdIsEncryptedIsOneToOneClosure: ((String, Bool, Bool) async throws -> Void)? + var applyPowerLevelChangesClosure: ((RoomPowerLevelChanges) async -> Result)? - func unmuteRoom(roomId: String, isEncrypted: Bool, isOneToOne: Bool) async throws { - if let error = unmuteRoomRoomIdIsEncryptedIsOneToOneThrowableError { - throw error - } - unmuteRoomRoomIdIsEncryptedIsOneToOneCallsCount += 1 - unmuteRoomRoomIdIsEncryptedIsOneToOneReceivedArguments = (roomId: roomId, isEncrypted: isEncrypted, isOneToOne: isOneToOne) + func applyPowerLevelChanges(_ changes: RoomPowerLevelChanges) async -> Result { + applyPowerLevelChangesCallsCount += 1 + applyPowerLevelChangesReceivedChanges = changes DispatchQueue.main.async { - self.unmuteRoomRoomIdIsEncryptedIsOneToOneReceivedInvocations.append((roomId: roomId, isEncrypted: isEncrypted, isOneToOne: isOneToOne)) + self.applyPowerLevelChangesReceivedInvocations.append(changes) + } + if let applyPowerLevelChangesClosure = applyPowerLevelChangesClosure { + return await applyPowerLevelChangesClosure(changes) + } else { + return applyPowerLevelChangesReturnValue } - try await unmuteRoomRoomIdIsEncryptedIsOneToOneClosure?(roomId, isEncrypted, isOneToOne) } - //MARK: - isRoomMentionEnabled + //MARK: - resetPowerLevels - var isRoomMentionEnabledThrowableError: Error? - var isRoomMentionEnabledUnderlyingCallsCount = 0 - var isRoomMentionEnabledCallsCount: Int { + var resetPowerLevelsUnderlyingCallsCount = 0 + var resetPowerLevelsCallsCount: Int { get { if Thread.isMainThread { - return isRoomMentionEnabledUnderlyingCallsCount + return resetPowerLevelsUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = isRoomMentionEnabledUnderlyingCallsCount + returnValue = resetPowerLevelsUnderlyingCallsCount } return returnValue! @@ -7099,27 +7145,27 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - isRoomMentionEnabledUnderlyingCallsCount = newValue + resetPowerLevelsUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - isRoomMentionEnabledUnderlyingCallsCount = newValue + resetPowerLevelsUnderlyingCallsCount = newValue } } } } - var isRoomMentionEnabledCalled: Bool { - return isRoomMentionEnabledCallsCount > 0 + var resetPowerLevelsCalled: Bool { + return resetPowerLevelsCallsCount > 0 } - var isRoomMentionEnabledUnderlyingReturnValue: Bool! - var isRoomMentionEnabledReturnValue: Bool! { + var resetPowerLevelsUnderlyingReturnValue: Result! + var resetPowerLevelsReturnValue: Result! { get { if Thread.isMainThread { - return isRoomMentionEnabledUnderlyingReturnValue + return resetPowerLevelsUnderlyingReturnValue } else { - var returnValue: Bool? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = isRoomMentionEnabledUnderlyingReturnValue + returnValue = resetPowerLevelsUnderlyingReturnValue } return returnValue! @@ -7127,39 +7173,35 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - isRoomMentionEnabledUnderlyingReturnValue = newValue + resetPowerLevelsUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - isRoomMentionEnabledUnderlyingReturnValue = newValue + resetPowerLevelsUnderlyingReturnValue = newValue } } } } - var isRoomMentionEnabledClosure: (() async throws -> Bool)? + var resetPowerLevelsClosure: (() async -> Result)? - func isRoomMentionEnabled() async throws -> Bool { - if let error = isRoomMentionEnabledThrowableError { - throw error - } - isRoomMentionEnabledCallsCount += 1 - if let isRoomMentionEnabledClosure = isRoomMentionEnabledClosure { - return try await isRoomMentionEnabledClosure() + func resetPowerLevels() async -> Result { + resetPowerLevelsCallsCount += 1 + if let resetPowerLevelsClosure = resetPowerLevelsClosure { + return await resetPowerLevelsClosure() } else { - return isRoomMentionEnabledReturnValue + return resetPowerLevelsReturnValue } } - //MARK: - setRoomMentionEnabled + //MARK: - suggestedRole - var setRoomMentionEnabledEnabledThrowableError: Error? - var setRoomMentionEnabledEnabledUnderlyingCallsCount = 0 - var setRoomMentionEnabledEnabledCallsCount: Int { + var suggestedRoleForUnderlyingCallsCount = 0 + var suggestedRoleForCallsCount: Int { get { if Thread.isMainThread { - return setRoomMentionEnabledEnabledUnderlyingCallsCount + return suggestedRoleForUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = setRoomMentionEnabledEnabledUnderlyingCallsCount + returnValue = suggestedRoleForUnderlyingCallsCount } return returnValue! @@ -7167,44 +7209,29 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - setRoomMentionEnabledEnabledUnderlyingCallsCount = newValue + suggestedRoleForUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - setRoomMentionEnabledEnabledUnderlyingCallsCount = newValue + suggestedRoleForUnderlyingCallsCount = newValue } } } } - var setRoomMentionEnabledEnabledCalled: Bool { - return setRoomMentionEnabledEnabledCallsCount > 0 - } - var setRoomMentionEnabledEnabledReceivedEnabled: Bool? - var setRoomMentionEnabledEnabledReceivedInvocations: [Bool] = [] - var setRoomMentionEnabledEnabledClosure: ((Bool) async throws -> Void)? - - func setRoomMentionEnabled(enabled: Bool) async throws { - if let error = setRoomMentionEnabledEnabledThrowableError { - throw error - } - setRoomMentionEnabledEnabledCallsCount += 1 - setRoomMentionEnabledEnabledReceivedEnabled = enabled - DispatchQueue.main.async { - self.setRoomMentionEnabledEnabledReceivedInvocations.append(enabled) - } - try await setRoomMentionEnabledEnabledClosure?(enabled) + var suggestedRoleForCalled: Bool { + return suggestedRoleForCallsCount > 0 } - //MARK: - isCallEnabled + var suggestedRoleForReceivedUserID: String? + var suggestedRoleForReceivedInvocations: [String] = [] - var isCallEnabledThrowableError: Error? - var isCallEnabledUnderlyingCallsCount = 0 - var isCallEnabledCallsCount: Int { + var suggestedRoleForUnderlyingReturnValue: Result! + var suggestedRoleForReturnValue: Result! { get { if Thread.isMainThread { - return isCallEnabledUnderlyingCallsCount + return suggestedRoleForUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = isCallEnabledUnderlyingCallsCount + returnValue = suggestedRoleForUnderlyingReturnValue } return returnValue! @@ -7212,27 +7239,39 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - isCallEnabledUnderlyingCallsCount = newValue + suggestedRoleForUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - isCallEnabledUnderlyingCallsCount = newValue + suggestedRoleForUnderlyingReturnValue = newValue } } } } - var isCallEnabledCalled: Bool { - return isCallEnabledCallsCount > 0 + var suggestedRoleForClosure: ((String) async -> Result)? + + func suggestedRole(for userID: String) async -> Result { + suggestedRoleForCallsCount += 1 + suggestedRoleForReceivedUserID = userID + DispatchQueue.main.async { + self.suggestedRoleForReceivedInvocations.append(userID) + } + if let suggestedRoleForClosure = suggestedRoleForClosure { + return await suggestedRoleForClosure(userID) + } else { + return suggestedRoleForReturnValue + } } + //MARK: - updatePowerLevelsForUsers - var isCallEnabledUnderlyingReturnValue: Bool! - var isCallEnabledReturnValue: Bool! { + var updatePowerLevelsForUsersUnderlyingCallsCount = 0 + var updatePowerLevelsForUsersCallsCount: Int { get { if Thread.isMainThread { - return isCallEnabledUnderlyingReturnValue + return updatePowerLevelsForUsersUnderlyingCallsCount } else { - var returnValue: Bool? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = isCallEnabledUnderlyingReturnValue + returnValue = updatePowerLevelsForUsersUnderlyingCallsCount } return returnValue! @@ -7240,39 +7279,29 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - isCallEnabledUnderlyingReturnValue = newValue + updatePowerLevelsForUsersUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - isCallEnabledUnderlyingReturnValue = newValue + updatePowerLevelsForUsersUnderlyingCallsCount = newValue } } } } - var isCallEnabledClosure: (() async throws -> Bool)? - - func isCallEnabled() async throws -> Bool { - if let error = isCallEnabledThrowableError { - throw error - } - isCallEnabledCallsCount += 1 - if let isCallEnabledClosure = isCallEnabledClosure { - return try await isCallEnabledClosure() - } else { - return isCallEnabledReturnValue - } + var updatePowerLevelsForUsersCalled: Bool { + return updatePowerLevelsForUsersCallsCount > 0 } - //MARK: - setCallEnabled + var updatePowerLevelsForUsersReceivedUpdates: [(userID: String, powerLevel: Int64)]? + var updatePowerLevelsForUsersReceivedInvocations: [[(userID: String, powerLevel: Int64)]] = [] - var setCallEnabledEnabledThrowableError: Error? - var setCallEnabledEnabledUnderlyingCallsCount = 0 - var setCallEnabledEnabledCallsCount: Int { + var updatePowerLevelsForUsersUnderlyingReturnValue: Result! + var updatePowerLevelsForUsersReturnValue: Result! { get { if Thread.isMainThread { - return setCallEnabledEnabledUnderlyingCallsCount + return updatePowerLevelsForUsersUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = setCallEnabledEnabledUnderlyingCallsCount + returnValue = updatePowerLevelsForUsersUnderlyingReturnValue } return returnValue! @@ -7280,44 +7309,39 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - setCallEnabledEnabledUnderlyingCallsCount = newValue + updatePowerLevelsForUsersUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - setCallEnabledEnabledUnderlyingCallsCount = newValue + updatePowerLevelsForUsersUnderlyingReturnValue = newValue } } } } - var setCallEnabledEnabledCalled: Bool { - return setCallEnabledEnabledCallsCount > 0 - } - var setCallEnabledEnabledReceivedEnabled: Bool? - var setCallEnabledEnabledReceivedInvocations: [Bool] = [] - var setCallEnabledEnabledClosure: ((Bool) async throws -> Void)? + var updatePowerLevelsForUsersClosure: (([(userID: String, powerLevel: Int64)]) async -> Result)? - func setCallEnabled(enabled: Bool) async throws { - if let error = setCallEnabledEnabledThrowableError { - throw error - } - setCallEnabledEnabledCallsCount += 1 - setCallEnabledEnabledReceivedEnabled = enabled + func updatePowerLevelsForUsers(_ updates: [(userID: String, powerLevel: Int64)]) async -> Result { + updatePowerLevelsForUsersCallsCount += 1 + updatePowerLevelsForUsersReceivedUpdates = updates DispatchQueue.main.async { - self.setCallEnabledEnabledReceivedInvocations.append(enabled) + self.updatePowerLevelsForUsersReceivedInvocations.append(updates) + } + if let updatePowerLevelsForUsersClosure = updatePowerLevelsForUsersClosure { + return await updatePowerLevelsForUsersClosure(updates) + } else { + return updatePowerLevelsForUsersReturnValue } - try await setCallEnabledEnabledClosure?(enabled) } - //MARK: - isInviteForMeEnabled + //MARK: - canUser - var isInviteForMeEnabledThrowableError: Error? - var isInviteForMeEnabledUnderlyingCallsCount = 0 - var isInviteForMeEnabledCallsCount: Int { + var canUserUserIDSendStateEventUnderlyingCallsCount = 0 + var canUserUserIDSendStateEventCallsCount: Int { get { if Thread.isMainThread { - return isInviteForMeEnabledUnderlyingCallsCount + return canUserUserIDSendStateEventUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = isInviteForMeEnabledUnderlyingCallsCount + returnValue = canUserUserIDSendStateEventUnderlyingCallsCount } return returnValue! @@ -7325,27 +7349,29 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - isInviteForMeEnabledUnderlyingCallsCount = newValue + canUserUserIDSendStateEventUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - isInviteForMeEnabledUnderlyingCallsCount = newValue + canUserUserIDSendStateEventUnderlyingCallsCount = newValue } } } } - var isInviteForMeEnabledCalled: Bool { - return isInviteForMeEnabledCallsCount > 0 + var canUserUserIDSendStateEventCalled: Bool { + return canUserUserIDSendStateEventCallsCount > 0 } + var canUserUserIDSendStateEventReceivedArguments: (userID: String, event: StateEventType)? + var canUserUserIDSendStateEventReceivedInvocations: [(userID: String, event: StateEventType)] = [] - var isInviteForMeEnabledUnderlyingReturnValue: Bool! - var isInviteForMeEnabledReturnValue: Bool! { + var canUserUserIDSendStateEventUnderlyingReturnValue: Result! + var canUserUserIDSendStateEventReturnValue: Result! { get { if Thread.isMainThread { - return isInviteForMeEnabledUnderlyingReturnValue + return canUserUserIDSendStateEventUnderlyingReturnValue } else { - var returnValue: Bool? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = isInviteForMeEnabledUnderlyingReturnValue + returnValue = canUserUserIDSendStateEventUnderlyingReturnValue } return returnValue! @@ -7353,39 +7379,39 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - isInviteForMeEnabledUnderlyingReturnValue = newValue + canUserUserIDSendStateEventUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - isInviteForMeEnabledUnderlyingReturnValue = newValue + canUserUserIDSendStateEventUnderlyingReturnValue = newValue } } } } - var isInviteForMeEnabledClosure: (() async throws -> Bool)? + var canUserUserIDSendStateEventClosure: ((String, StateEventType) async -> Result)? - func isInviteForMeEnabled() async throws -> Bool { - if let error = isInviteForMeEnabledThrowableError { - throw error + func canUser(userID: String, sendStateEvent event: StateEventType) async -> Result { + canUserUserIDSendStateEventCallsCount += 1 + canUserUserIDSendStateEventReceivedArguments = (userID: userID, event: event) + DispatchQueue.main.async { + self.canUserUserIDSendStateEventReceivedInvocations.append((userID: userID, event: event)) } - isInviteForMeEnabledCallsCount += 1 - if let isInviteForMeEnabledClosure = isInviteForMeEnabledClosure { - return try await isInviteForMeEnabledClosure() + if let canUserUserIDSendStateEventClosure = canUserUserIDSendStateEventClosure { + return await canUserUserIDSendStateEventClosure(userID, event) } else { - return isInviteForMeEnabledReturnValue + return canUserUserIDSendStateEventReturnValue } } - //MARK: - setInviteForMeEnabled + //MARK: - canUserInvite - var setInviteForMeEnabledEnabledThrowableError: Error? - var setInviteForMeEnabledEnabledUnderlyingCallsCount = 0 - var setInviteForMeEnabledEnabledCallsCount: Int { + var canUserInviteUserIDUnderlyingCallsCount = 0 + var canUserInviteUserIDCallsCount: Int { get { if Thread.isMainThread { - return setInviteForMeEnabledEnabledUnderlyingCallsCount + return canUserInviteUserIDUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = setInviteForMeEnabledEnabledUnderlyingCallsCount + returnValue = canUserInviteUserIDUnderlyingCallsCount } return returnValue! @@ -7393,44 +7419,29 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - setInviteForMeEnabledEnabledUnderlyingCallsCount = newValue + canUserInviteUserIDUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - setInviteForMeEnabledEnabledUnderlyingCallsCount = newValue + canUserInviteUserIDUnderlyingCallsCount = newValue } } } } - var setInviteForMeEnabledEnabledCalled: Bool { - return setInviteForMeEnabledEnabledCallsCount > 0 - } - var setInviteForMeEnabledEnabledReceivedEnabled: Bool? - var setInviteForMeEnabledEnabledReceivedInvocations: [Bool] = [] - var setInviteForMeEnabledEnabledClosure: ((Bool) async throws -> Void)? - - func setInviteForMeEnabled(enabled: Bool) async throws { - if let error = setInviteForMeEnabledEnabledThrowableError { - throw error - } - setInviteForMeEnabledEnabledCallsCount += 1 - setInviteForMeEnabledEnabledReceivedEnabled = enabled - DispatchQueue.main.async { - self.setInviteForMeEnabledEnabledReceivedInvocations.append(enabled) - } - try await setInviteForMeEnabledEnabledClosure?(enabled) + var canUserInviteUserIDCalled: Bool { + return canUserInviteUserIDCallsCount > 0 } - //MARK: - getRoomsWithUserDefinedRules + var canUserInviteUserIDReceivedUserID: String? + var canUserInviteUserIDReceivedInvocations: [String] = [] - var getRoomsWithUserDefinedRulesThrowableError: Error? - var getRoomsWithUserDefinedRulesUnderlyingCallsCount = 0 - var getRoomsWithUserDefinedRulesCallsCount: Int { + var canUserInviteUserIDUnderlyingReturnValue: Result! + var canUserInviteUserIDReturnValue: Result! { get { if Thread.isMainThread { - return getRoomsWithUserDefinedRulesUnderlyingCallsCount + return canUserInviteUserIDUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = getRoomsWithUserDefinedRulesUnderlyingCallsCount + returnValue = canUserInviteUserIDUnderlyingReturnValue } return returnValue! @@ -7438,27 +7449,39 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - getRoomsWithUserDefinedRulesUnderlyingCallsCount = newValue + canUserInviteUserIDUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - getRoomsWithUserDefinedRulesUnderlyingCallsCount = newValue + canUserInviteUserIDUnderlyingReturnValue = newValue } } } } - var getRoomsWithUserDefinedRulesCalled: Bool { - return getRoomsWithUserDefinedRulesCallsCount > 0 + var canUserInviteUserIDClosure: ((String) async -> Result)? + + func canUserInvite(userID: String) async -> Result { + canUserInviteUserIDCallsCount += 1 + canUserInviteUserIDReceivedUserID = userID + DispatchQueue.main.async { + self.canUserInviteUserIDReceivedInvocations.append(userID) + } + if let canUserInviteUserIDClosure = canUserInviteUserIDClosure { + return await canUserInviteUserIDClosure(userID) + } else { + return canUserInviteUserIDReturnValue + } } + //MARK: - canUserRedactOther - var getRoomsWithUserDefinedRulesUnderlyingReturnValue: [String]! - var getRoomsWithUserDefinedRulesReturnValue: [String]! { + var canUserRedactOtherUserIDUnderlyingCallsCount = 0 + var canUserRedactOtherUserIDCallsCount: Int { get { if Thread.isMainThread { - return getRoomsWithUserDefinedRulesUnderlyingReturnValue + return canUserRedactOtherUserIDUnderlyingCallsCount } else { - var returnValue: [String]? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = getRoomsWithUserDefinedRulesUnderlyingReturnValue + returnValue = canUserRedactOtherUserIDUnderlyingCallsCount } return returnValue! @@ -7466,38 +7489,29 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - getRoomsWithUserDefinedRulesUnderlyingReturnValue = newValue + canUserRedactOtherUserIDUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - getRoomsWithUserDefinedRulesUnderlyingReturnValue = newValue + canUserRedactOtherUserIDUnderlyingCallsCount = newValue } } } } - var getRoomsWithUserDefinedRulesClosure: (() async throws -> [String])? - - func getRoomsWithUserDefinedRules() async throws -> [String] { - if let error = getRoomsWithUserDefinedRulesThrowableError { - throw error - } - getRoomsWithUserDefinedRulesCallsCount += 1 - if let getRoomsWithUserDefinedRulesClosure = getRoomsWithUserDefinedRulesClosure { - return try await getRoomsWithUserDefinedRulesClosure() - } else { - return getRoomsWithUserDefinedRulesReturnValue - } + var canUserRedactOtherUserIDCalled: Bool { + return canUserRedactOtherUserIDCallsCount > 0 } - //MARK: - canPushEncryptedEventsToDevice + var canUserRedactOtherUserIDReceivedUserID: String? + var canUserRedactOtherUserIDReceivedInvocations: [String] = [] - var canPushEncryptedEventsToDeviceUnderlyingCallsCount = 0 - var canPushEncryptedEventsToDeviceCallsCount: Int { + var canUserRedactOtherUserIDUnderlyingReturnValue: Result! + var canUserRedactOtherUserIDReturnValue: Result! { get { if Thread.isMainThread { - return canPushEncryptedEventsToDeviceUnderlyingCallsCount + return canUserRedactOtherUserIDUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = canPushEncryptedEventsToDeviceUnderlyingCallsCount + returnValue = canUserRedactOtherUserIDUnderlyingReturnValue } return returnValue! @@ -7505,27 +7519,39 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - canPushEncryptedEventsToDeviceUnderlyingCallsCount = newValue + canUserRedactOtherUserIDUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - canPushEncryptedEventsToDeviceUnderlyingCallsCount = newValue + canUserRedactOtherUserIDUnderlyingReturnValue = newValue } } } } - var canPushEncryptedEventsToDeviceCalled: Bool { - return canPushEncryptedEventsToDeviceCallsCount > 0 - } + var canUserRedactOtherUserIDClosure: ((String) async -> Result)? - var canPushEncryptedEventsToDeviceUnderlyingReturnValue: Bool! - var canPushEncryptedEventsToDeviceReturnValue: Bool! { + func canUserRedactOther(userID: String) async -> Result { + canUserRedactOtherUserIDCallsCount += 1 + canUserRedactOtherUserIDReceivedUserID = userID + DispatchQueue.main.async { + self.canUserRedactOtherUserIDReceivedInvocations.append(userID) + } + if let canUserRedactOtherUserIDClosure = canUserRedactOtherUserIDClosure { + return await canUserRedactOtherUserIDClosure(userID) + } else { + return canUserRedactOtherUserIDReturnValue + } + } + //MARK: - canUserRedactOwn + + var canUserRedactOwnUserIDUnderlyingCallsCount = 0 + var canUserRedactOwnUserIDCallsCount: Int { get { if Thread.isMainThread { - return canPushEncryptedEventsToDeviceUnderlyingReturnValue + return canUserRedactOwnUserIDUnderlyingCallsCount } else { - var returnValue: Bool? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = canPushEncryptedEventsToDeviceUnderlyingReturnValue + returnValue = canUserRedactOwnUserIDUnderlyingCallsCount } return returnValue! @@ -7533,38 +7559,29 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { } set { if Thread.isMainThread { - canPushEncryptedEventsToDeviceUnderlyingReturnValue = newValue + canUserRedactOwnUserIDUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - canPushEncryptedEventsToDeviceUnderlyingReturnValue = newValue + canUserRedactOwnUserIDUnderlyingCallsCount = newValue } } } } - var canPushEncryptedEventsToDeviceClosure: (() async -> Bool)? - - func canPushEncryptedEventsToDevice() async -> Bool { - canPushEncryptedEventsToDeviceCallsCount += 1 - if let canPushEncryptedEventsToDeviceClosure = canPushEncryptedEventsToDeviceClosure { - return await canPushEncryptedEventsToDeviceClosure() - } else { - return canPushEncryptedEventsToDeviceReturnValue - } + var canUserRedactOwnUserIDCalled: Bool { + return canUserRedactOwnUserIDCallsCount > 0 } -} -class OrientationManagerMock: OrientationManagerProtocol { - - //MARK: - setOrientation + var canUserRedactOwnUserIDReceivedUserID: String? + var canUserRedactOwnUserIDReceivedInvocations: [String] = [] - var setOrientationUnderlyingCallsCount = 0 - var setOrientationCallsCount: Int { + var canUserRedactOwnUserIDUnderlyingReturnValue: Result! + var canUserRedactOwnUserIDReturnValue: Result! { get { if Thread.isMainThread { - return setOrientationUnderlyingCallsCount + return canUserRedactOwnUserIDUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = setOrientationUnderlyingCallsCount + returnValue = canUserRedactOwnUserIDUnderlyingReturnValue } return returnValue! @@ -7572,40 +7589,39 @@ class OrientationManagerMock: OrientationManagerProtocol { } set { if Thread.isMainThread { - setOrientationUnderlyingCallsCount = newValue + canUserRedactOwnUserIDUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - setOrientationUnderlyingCallsCount = newValue + canUserRedactOwnUserIDUnderlyingReturnValue = newValue } } } } - var setOrientationCalled: Bool { - return setOrientationCallsCount > 0 - } - var setOrientationReceivedOrientation: UIInterfaceOrientationMask? - var setOrientationReceivedInvocations: [UIInterfaceOrientationMask] = [] - var setOrientationClosure: ((UIInterfaceOrientationMask) -> Void)? + var canUserRedactOwnUserIDClosure: ((String) async -> Result)? - func setOrientation(_ orientation: UIInterfaceOrientationMask) { - setOrientationCallsCount += 1 - setOrientationReceivedOrientation = orientation + func canUserRedactOwn(userID: String) async -> Result { + canUserRedactOwnUserIDCallsCount += 1 + canUserRedactOwnUserIDReceivedUserID = userID DispatchQueue.main.async { - self.setOrientationReceivedInvocations.append(orientation) + self.canUserRedactOwnUserIDReceivedInvocations.append(userID) + } + if let canUserRedactOwnUserIDClosure = canUserRedactOwnUserIDClosure { + return await canUserRedactOwnUserIDClosure(userID) + } else { + return canUserRedactOwnUserIDReturnValue } - setOrientationClosure?(orientation) } - //MARK: - lockOrientation + //MARK: - canUserKick - var lockOrientationUnderlyingCallsCount = 0 - var lockOrientationCallsCount: Int { + var canUserKickUserIDUnderlyingCallsCount = 0 + var canUserKickUserIDCallsCount: Int { get { if Thread.isMainThread { - return lockOrientationUnderlyingCallsCount + return canUserKickUserIDUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = lockOrientationUnderlyingCallsCount + returnValue = canUserKickUserIDUnderlyingCallsCount } return returnValue! @@ -7613,43 +7629,29 @@ class OrientationManagerMock: OrientationManagerProtocol { } set { if Thread.isMainThread { - lockOrientationUnderlyingCallsCount = newValue + canUserKickUserIDUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - lockOrientationUnderlyingCallsCount = newValue + canUserKickUserIDUnderlyingCallsCount = newValue } } } } - var lockOrientationCalled: Bool { - return lockOrientationCallsCount > 0 - } - var lockOrientationReceivedOrientation: UIInterfaceOrientationMask? - var lockOrientationReceivedInvocations: [UIInterfaceOrientationMask] = [] - var lockOrientationClosure: ((UIInterfaceOrientationMask) -> Void)? - - func lockOrientation(_ orientation: UIInterfaceOrientationMask) { - lockOrientationCallsCount += 1 - lockOrientationReceivedOrientation = orientation - DispatchQueue.main.async { - self.lockOrientationReceivedInvocations.append(orientation) - } - lockOrientationClosure?(orientation) + var canUserKickUserIDCalled: Bool { + return canUserKickUserIDCallsCount > 0 } -} -class PHGPostHogMock: PHGPostHogProtocol { - - //MARK: - optIn + var canUserKickUserIDReceivedUserID: String? + var canUserKickUserIDReceivedInvocations: [String] = [] - var optInUnderlyingCallsCount = 0 - var optInCallsCount: Int { + var canUserKickUserIDUnderlyingReturnValue: Result! + var canUserKickUserIDReturnValue: Result! { get { if Thread.isMainThread { - return optInUnderlyingCallsCount + return canUserKickUserIDUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = optInUnderlyingCallsCount + returnValue = canUserKickUserIDUnderlyingReturnValue } return returnValue! @@ -7657,34 +7659,39 @@ class PHGPostHogMock: PHGPostHogProtocol { } set { if Thread.isMainThread { - optInUnderlyingCallsCount = newValue + canUserKickUserIDUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - optInUnderlyingCallsCount = newValue + canUserKickUserIDUnderlyingReturnValue = newValue } } } } - var optInCalled: Bool { - return optInCallsCount > 0 - } - var optInClosure: (() -> Void)? + var canUserKickUserIDClosure: ((String) async -> Result)? - func optIn() { - optInCallsCount += 1 - optInClosure?() + func canUserKick(userID: String) async -> Result { + canUserKickUserIDCallsCount += 1 + canUserKickUserIDReceivedUserID = userID + DispatchQueue.main.async { + self.canUserKickUserIDReceivedInvocations.append(userID) + } + if let canUserKickUserIDClosure = canUserKickUserIDClosure { + return await canUserKickUserIDClosure(userID) + } else { + return canUserKickUserIDReturnValue + } } - //MARK: - optOut + //MARK: - canUserBan - var optOutUnderlyingCallsCount = 0 - var optOutCallsCount: Int { + var canUserBanUserIDUnderlyingCallsCount = 0 + var canUserBanUserIDCallsCount: Int { get { if Thread.isMainThread { - return optOutUnderlyingCallsCount + return canUserBanUserIDUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = optOutUnderlyingCallsCount + returnValue = canUserBanUserIDUnderlyingCallsCount } return returnValue! @@ -7692,34 +7699,29 @@ class PHGPostHogMock: PHGPostHogProtocol { } set { if Thread.isMainThread { - optOutUnderlyingCallsCount = newValue + canUserBanUserIDUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - optOutUnderlyingCallsCount = newValue + canUserBanUserIDUnderlyingCallsCount = newValue } } } } - var optOutCalled: Bool { - return optOutCallsCount > 0 - } - var optOutClosure: (() -> Void)? - - func optOut() { - optOutCallsCount += 1 - optOutClosure?() + var canUserBanUserIDCalled: Bool { + return canUserBanUserIDCallsCount > 0 } - //MARK: - reset + var canUserBanUserIDReceivedUserID: String? + var canUserBanUserIDReceivedInvocations: [String] = [] - var resetUnderlyingCallsCount = 0 - var resetCallsCount: Int { + var canUserBanUserIDUnderlyingReturnValue: Result! + var canUserBanUserIDReturnValue: Result! { get { if Thread.isMainThread { - return resetUnderlyingCallsCount + return canUserBanUserIDUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = resetUnderlyingCallsCount + returnValue = canUserBanUserIDUnderlyingReturnValue } return returnValue! @@ -7727,34 +7729,39 @@ class PHGPostHogMock: PHGPostHogProtocol { } set { if Thread.isMainThread { - resetUnderlyingCallsCount = newValue + canUserBanUserIDUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - resetUnderlyingCallsCount = newValue + canUserBanUserIDUnderlyingReturnValue = newValue } } } } - var resetCalled: Bool { - return resetCallsCount > 0 - } - var resetClosure: (() -> Void)? + var canUserBanUserIDClosure: ((String) async -> Result)? - func reset() { - resetCallsCount += 1 - resetClosure?() + func canUserBan(userID: String) async -> Result { + canUserBanUserIDCallsCount += 1 + canUserBanUserIDReceivedUserID = userID + DispatchQueue.main.async { + self.canUserBanUserIDReceivedInvocations.append(userID) + } + if let canUserBanUserIDClosure = canUserBanUserIDClosure { + return await canUserBanUserIDClosure(userID) + } else { + return canUserBanUserIDReturnValue + } } - //MARK: - capture + //MARK: - canUserTriggerRoomNotification - var capturePropertiesUserPropertiesUnderlyingCallsCount = 0 - var capturePropertiesUserPropertiesCallsCount: Int { + var canUserTriggerRoomNotificationUserIDUnderlyingCallsCount = 0 + var canUserTriggerRoomNotificationUserIDCallsCount: Int { get { if Thread.isMainThread { - return capturePropertiesUserPropertiesUnderlyingCallsCount + return canUserTriggerRoomNotificationUserIDUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = capturePropertiesUserPropertiesUnderlyingCallsCount + returnValue = canUserTriggerRoomNotificationUserIDUnderlyingCallsCount } return returnValue! @@ -7762,40 +7769,29 @@ class PHGPostHogMock: PHGPostHogProtocol { } set { if Thread.isMainThread { - capturePropertiesUserPropertiesUnderlyingCallsCount = newValue + canUserTriggerRoomNotificationUserIDUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - capturePropertiesUserPropertiesUnderlyingCallsCount = newValue + canUserTriggerRoomNotificationUserIDUnderlyingCallsCount = newValue } } } } - var capturePropertiesUserPropertiesCalled: Bool { - return capturePropertiesUserPropertiesCallsCount > 0 - } - var capturePropertiesUserPropertiesReceivedArguments: (event: String, properties: [String: Any]?, userProperties: [String: Any]?)? - var capturePropertiesUserPropertiesReceivedInvocations: [(event: String, properties: [String: Any]?, userProperties: [String: Any]?)] = [] - var capturePropertiesUserPropertiesClosure: ((String, [String: Any]?, [String: Any]?) -> Void)? - - func capture(_ event: String, properties: [String: Any]?, userProperties: [String: Any]?) { - capturePropertiesUserPropertiesCallsCount += 1 - capturePropertiesUserPropertiesReceivedArguments = (event: event, properties: properties, userProperties: userProperties) - DispatchQueue.main.async { - self.capturePropertiesUserPropertiesReceivedInvocations.append((event: event, properties: properties, userProperties: userProperties)) - } - capturePropertiesUserPropertiesClosure?(event, properties, userProperties) + var canUserTriggerRoomNotificationUserIDCalled: Bool { + return canUserTriggerRoomNotificationUserIDCallsCount > 0 } - //MARK: - screen + var canUserTriggerRoomNotificationUserIDReceivedUserID: String? + var canUserTriggerRoomNotificationUserIDReceivedInvocations: [String] = [] - var screenPropertiesUnderlyingCallsCount = 0 - var screenPropertiesCallsCount: Int { + var canUserTriggerRoomNotificationUserIDUnderlyingReturnValue: Result! + var canUserTriggerRoomNotificationUserIDReturnValue: Result! { get { if Thread.isMainThread { - return screenPropertiesUnderlyingCallsCount + return canUserTriggerRoomNotificationUserIDUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = screenPropertiesUnderlyingCallsCount + returnValue = canUserTriggerRoomNotificationUserIDUnderlyingReturnValue } return returnValue! @@ -7803,43 +7799,39 @@ class PHGPostHogMock: PHGPostHogProtocol { } set { if Thread.isMainThread { - screenPropertiesUnderlyingCallsCount = newValue + canUserTriggerRoomNotificationUserIDUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - screenPropertiesUnderlyingCallsCount = newValue + canUserTriggerRoomNotificationUserIDUnderlyingReturnValue = newValue } } } } - var screenPropertiesCalled: Bool { - return screenPropertiesCallsCount > 0 - } - var screenPropertiesReceivedArguments: (screenTitle: String, properties: [String: Any]?)? - var screenPropertiesReceivedInvocations: [(screenTitle: String, properties: [String: Any]?)] = [] - var screenPropertiesClosure: ((String, [String: Any]?) -> Void)? + var canUserTriggerRoomNotificationUserIDClosure: ((String) async -> Result)? - func screen(_ screenTitle: String, properties: [String: Any]?) { - screenPropertiesCallsCount += 1 - screenPropertiesReceivedArguments = (screenTitle: screenTitle, properties: properties) + func canUserTriggerRoomNotification(userID: String) async -> Result { + canUserTriggerRoomNotificationUserIDCallsCount += 1 + canUserTriggerRoomNotificationUserIDReceivedUserID = userID DispatchQueue.main.async { - self.screenPropertiesReceivedInvocations.append((screenTitle: screenTitle, properties: properties)) + self.canUserTriggerRoomNotificationUserIDReceivedInvocations.append(userID) + } + if let canUserTriggerRoomNotificationUserIDClosure = canUserTriggerRoomNotificationUserIDClosure { + return await canUserTriggerRoomNotificationUserIDClosure(userID) + } else { + return canUserTriggerRoomNotificationUserIDReturnValue } - screenPropertiesClosure?(screenTitle, properties) } -} -class PollInteractionHandlerMock: PollInteractionHandlerProtocol { - - //MARK: - sendPollResponse + //MARK: - canUserPinOrUnpin - var sendPollResponsePollStartIDOptionIDUnderlyingCallsCount = 0 - var sendPollResponsePollStartIDOptionIDCallsCount: Int { + var canUserPinOrUnpinUserIDUnderlyingCallsCount = 0 + var canUserPinOrUnpinUserIDCallsCount: Int { get { if Thread.isMainThread { - return sendPollResponsePollStartIDOptionIDUnderlyingCallsCount + return canUserPinOrUnpinUserIDUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = sendPollResponsePollStartIDOptionIDUnderlyingCallsCount + returnValue = canUserPinOrUnpinUserIDUnderlyingCallsCount } return returnValue! @@ -7847,29 +7839,29 @@ class PollInteractionHandlerMock: PollInteractionHandlerProtocol { } set { if Thread.isMainThread { - sendPollResponsePollStartIDOptionIDUnderlyingCallsCount = newValue + canUserPinOrUnpinUserIDUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - sendPollResponsePollStartIDOptionIDUnderlyingCallsCount = newValue + canUserPinOrUnpinUserIDUnderlyingCallsCount = newValue } } } } - var sendPollResponsePollStartIDOptionIDCalled: Bool { - return sendPollResponsePollStartIDOptionIDCallsCount > 0 + var canUserPinOrUnpinUserIDCalled: Bool { + return canUserPinOrUnpinUserIDCallsCount > 0 } - var sendPollResponsePollStartIDOptionIDReceivedArguments: (pollStartID: String, optionID: String)? - var sendPollResponsePollStartIDOptionIDReceivedInvocations: [(pollStartID: String, optionID: String)] = [] + var canUserPinOrUnpinUserIDReceivedUserID: String? + var canUserPinOrUnpinUserIDReceivedInvocations: [String] = [] - var sendPollResponsePollStartIDOptionIDUnderlyingReturnValue: Result! - var sendPollResponsePollStartIDOptionIDReturnValue: Result! { + var canUserPinOrUnpinUserIDUnderlyingReturnValue: Result! + var canUserPinOrUnpinUserIDReturnValue: Result! { get { if Thread.isMainThread { - return sendPollResponsePollStartIDOptionIDUnderlyingReturnValue + return canUserPinOrUnpinUserIDUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = sendPollResponsePollStartIDOptionIDUnderlyingReturnValue + returnValue = canUserPinOrUnpinUserIDUnderlyingReturnValue } return returnValue! @@ -7877,39 +7869,39 @@ class PollInteractionHandlerMock: PollInteractionHandlerProtocol { } set { if Thread.isMainThread { - sendPollResponsePollStartIDOptionIDUnderlyingReturnValue = newValue + canUserPinOrUnpinUserIDUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - sendPollResponsePollStartIDOptionIDUnderlyingReturnValue = newValue + canUserPinOrUnpinUserIDUnderlyingReturnValue = newValue } } } } - var sendPollResponsePollStartIDOptionIDClosure: ((String, String) async -> Result)? + var canUserPinOrUnpinUserIDClosure: ((String) async -> Result)? - func sendPollResponse(pollStartID: String, optionID: String) async -> Result { - sendPollResponsePollStartIDOptionIDCallsCount += 1 - sendPollResponsePollStartIDOptionIDReceivedArguments = (pollStartID: pollStartID, optionID: optionID) + func canUserPinOrUnpin(userID: String) async -> Result { + canUserPinOrUnpinUserIDCallsCount += 1 + canUserPinOrUnpinUserIDReceivedUserID = userID DispatchQueue.main.async { - self.sendPollResponsePollStartIDOptionIDReceivedInvocations.append((pollStartID: pollStartID, optionID: optionID)) + self.canUserPinOrUnpinUserIDReceivedInvocations.append(userID) } - if let sendPollResponsePollStartIDOptionIDClosure = sendPollResponsePollStartIDOptionIDClosure { - return await sendPollResponsePollStartIDOptionIDClosure(pollStartID, optionID) + if let canUserPinOrUnpinUserIDClosure = canUserPinOrUnpinUserIDClosure { + return await canUserPinOrUnpinUserIDClosure(userID) } else { - return sendPollResponsePollStartIDOptionIDReturnValue + return canUserPinOrUnpinUserIDReturnValue } } - //MARK: - endPoll + //MARK: - kickUser - var endPollPollStartIDUnderlyingCallsCount = 0 - var endPollPollStartIDCallsCount: Int { + var kickUserUnderlyingCallsCount = 0 + var kickUserCallsCount: Int { get { if Thread.isMainThread { - return endPollPollStartIDUnderlyingCallsCount + return kickUserUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = endPollPollStartIDUnderlyingCallsCount + returnValue = kickUserUnderlyingCallsCount } return returnValue! @@ -7917,29 +7909,29 @@ class PollInteractionHandlerMock: PollInteractionHandlerProtocol { } set { if Thread.isMainThread { - endPollPollStartIDUnderlyingCallsCount = newValue + kickUserUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - endPollPollStartIDUnderlyingCallsCount = newValue + kickUserUnderlyingCallsCount = newValue } } } } - var endPollPollStartIDCalled: Bool { - return endPollPollStartIDCallsCount > 0 + var kickUserCalled: Bool { + return kickUserCallsCount > 0 } - var endPollPollStartIDReceivedPollStartID: String? - var endPollPollStartIDReceivedInvocations: [String] = [] + var kickUserReceivedUserID: String? + var kickUserReceivedInvocations: [String] = [] - var endPollPollStartIDUnderlyingReturnValue: Result! - var endPollPollStartIDReturnValue: Result! { + var kickUserUnderlyingReturnValue: Result! + var kickUserReturnValue: Result! { get { if Thread.isMainThread { - return endPollPollStartIDUnderlyingReturnValue + return kickUserUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = endPollPollStartIDUnderlyingReturnValue + returnValue = kickUserUnderlyingReturnValue } return returnValue! @@ -7947,47 +7939,39 @@ class PollInteractionHandlerMock: PollInteractionHandlerProtocol { } set { if Thread.isMainThread { - endPollPollStartIDUnderlyingReturnValue = newValue + kickUserUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - endPollPollStartIDUnderlyingReturnValue = newValue + kickUserUnderlyingReturnValue = newValue } } } } - var endPollPollStartIDClosure: ((String) async -> Result)? + var kickUserClosure: ((String) async -> Result)? - func endPoll(pollStartID: String) async -> Result { - endPollPollStartIDCallsCount += 1 - endPollPollStartIDReceivedPollStartID = pollStartID + func kickUser(_ userID: String) async -> Result { + kickUserCallsCount += 1 + kickUserReceivedUserID = userID DispatchQueue.main.async { - self.endPollPollStartIDReceivedInvocations.append(pollStartID) + self.kickUserReceivedInvocations.append(userID) } - if let endPollPollStartIDClosure = endPollPollStartIDClosure { - return await endPollPollStartIDClosure(pollStartID) + if let kickUserClosure = kickUserClosure { + return await kickUserClosure(userID) } else { - return endPollPollStartIDReturnValue + return kickUserReturnValue } } -} -class QRCodeLoginServiceMock: QRCodeLoginServiceProtocol { - var qrLoginProgressPublisher: AnyPublisher { - get { return underlyingQrLoginProgressPublisher } - set(value) { underlyingQrLoginProgressPublisher = value } - } - var underlyingQrLoginProgressPublisher: AnyPublisher! - - //MARK: - loginWithQRCode + //MARK: - banUser - var loginWithQRCodeDataUnderlyingCallsCount = 0 - var loginWithQRCodeDataCallsCount: Int { + var banUserUnderlyingCallsCount = 0 + var banUserCallsCount: Int { get { if Thread.isMainThread { - return loginWithQRCodeDataUnderlyingCallsCount + return banUserUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = loginWithQRCodeDataUnderlyingCallsCount + returnValue = banUserUnderlyingCallsCount } return returnValue! @@ -7995,29 +7979,29 @@ class QRCodeLoginServiceMock: QRCodeLoginServiceProtocol { } set { if Thread.isMainThread { - loginWithQRCodeDataUnderlyingCallsCount = newValue + banUserUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - loginWithQRCodeDataUnderlyingCallsCount = newValue + banUserUnderlyingCallsCount = newValue } } } } - var loginWithQRCodeDataCalled: Bool { - return loginWithQRCodeDataCallsCount > 0 + var banUserCalled: Bool { + return banUserCallsCount > 0 } - var loginWithQRCodeDataReceivedData: Data? - var loginWithQRCodeDataReceivedInvocations: [Data] = [] + var banUserReceivedUserID: String? + var banUserReceivedInvocations: [String] = [] - var loginWithQRCodeDataUnderlyingReturnValue: Result! - var loginWithQRCodeDataReturnValue: Result! { + var banUserUnderlyingReturnValue: Result! + var banUserReturnValue: Result! { get { if Thread.isMainThread { - return loginWithQRCodeDataUnderlyingReturnValue + return banUserUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = loginWithQRCodeDataUnderlyingReturnValue + returnValue = banUserUnderlyingReturnValue } return returnValue! @@ -8025,47 +8009,39 @@ class QRCodeLoginServiceMock: QRCodeLoginServiceProtocol { } set { if Thread.isMainThread { - loginWithQRCodeDataUnderlyingReturnValue = newValue + banUserUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - loginWithQRCodeDataUnderlyingReturnValue = newValue + banUserUnderlyingReturnValue = newValue } } } } - var loginWithQRCodeDataClosure: ((Data) async -> Result)? + var banUserClosure: ((String) async -> Result)? - func loginWithQRCode(data: Data) async -> Result { - loginWithQRCodeDataCallsCount += 1 - loginWithQRCodeDataReceivedData = data + func banUser(_ userID: String) async -> Result { + banUserCallsCount += 1 + banUserReceivedUserID = userID DispatchQueue.main.async { - self.loginWithQRCodeDataReceivedInvocations.append(data) + self.banUserReceivedInvocations.append(userID) } - if let loginWithQRCodeDataClosure = loginWithQRCodeDataClosure { - return await loginWithQRCodeDataClosure(data) + if let banUserClosure = banUserClosure { + return await banUserClosure(userID) } else { - return loginWithQRCodeDataReturnValue + return banUserReturnValue } } -} -class RoomDirectorySearchProxyMock: RoomDirectorySearchProxyProtocol { - var resultsPublisher: CurrentValuePublisher<[RoomDirectorySearchResult], Never> { - get { return underlyingResultsPublisher } - set(value) { underlyingResultsPublisher = value } - } - var underlyingResultsPublisher: CurrentValuePublisher<[RoomDirectorySearchResult], Never>! - - //MARK: - search + //MARK: - unbanUser - var searchQueryUnderlyingCallsCount = 0 - var searchQueryCallsCount: Int { + var unbanUserUnderlyingCallsCount = 0 + var unbanUserCallsCount: Int { get { if Thread.isMainThread { - return searchQueryUnderlyingCallsCount + return unbanUserUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = searchQueryUnderlyingCallsCount + returnValue = unbanUserUnderlyingCallsCount } return returnValue! @@ -8073,29 +8049,29 @@ class RoomDirectorySearchProxyMock: RoomDirectorySearchProxyProtocol { } set { if Thread.isMainThread { - searchQueryUnderlyingCallsCount = newValue + unbanUserUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - searchQueryUnderlyingCallsCount = newValue + unbanUserUnderlyingCallsCount = newValue } } } } - var searchQueryCalled: Bool { - return searchQueryCallsCount > 0 + var unbanUserCalled: Bool { + return unbanUserCallsCount > 0 } - var searchQueryReceivedQuery: String? - var searchQueryReceivedInvocations: [String?] = [] + var unbanUserReceivedUserID: String? + var unbanUserReceivedInvocations: [String] = [] - var searchQueryUnderlyingReturnValue: Result! - var searchQueryReturnValue: Result! { + var unbanUserUnderlyingReturnValue: Result! + var unbanUserReturnValue: Result! { get { if Thread.isMainThread { - return searchQueryUnderlyingReturnValue + return unbanUserUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = searchQueryUnderlyingReturnValue + returnValue = unbanUserUnderlyingReturnValue } return returnValue! @@ -8103,39 +8079,39 @@ class RoomDirectorySearchProxyMock: RoomDirectorySearchProxyProtocol { } set { if Thread.isMainThread { - searchQueryUnderlyingReturnValue = newValue + unbanUserUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - searchQueryUnderlyingReturnValue = newValue + unbanUserUnderlyingReturnValue = newValue } } } } - var searchQueryClosure: ((String?) async -> Result)? + var unbanUserClosure: ((String) async -> Result)? - func search(query: String?) async -> Result { - searchQueryCallsCount += 1 - searchQueryReceivedQuery = query + func unbanUser(_ userID: String) async -> Result { + unbanUserCallsCount += 1 + unbanUserReceivedUserID = userID DispatchQueue.main.async { - self.searchQueryReceivedInvocations.append(query) + self.unbanUserReceivedInvocations.append(userID) } - if let searchQueryClosure = searchQueryClosure { - return await searchQueryClosure(query) + if let unbanUserClosure = unbanUserClosure { + return await unbanUserClosure(userID) } else { - return searchQueryReturnValue + return unbanUserReturnValue } } - //MARK: - nextPage + //MARK: - canUserJoinCall - var nextPageUnderlyingCallsCount = 0 - var nextPageCallsCount: Int { + var canUserJoinCallUserIDUnderlyingCallsCount = 0 + var canUserJoinCallUserIDCallsCount: Int { get { if Thread.isMainThread { - return nextPageUnderlyingCallsCount + return canUserJoinCallUserIDUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = nextPageUnderlyingCallsCount + returnValue = canUserJoinCallUserIDUnderlyingCallsCount } return returnValue! @@ -8143,27 +8119,29 @@ class RoomDirectorySearchProxyMock: RoomDirectorySearchProxyProtocol { } set { if Thread.isMainThread { - nextPageUnderlyingCallsCount = newValue + canUserJoinCallUserIDUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - nextPageUnderlyingCallsCount = newValue + canUserJoinCallUserIDUnderlyingCallsCount = newValue } } } } - var nextPageCalled: Bool { - return nextPageCallsCount > 0 + var canUserJoinCallUserIDCalled: Bool { + return canUserJoinCallUserIDCallsCount > 0 } + var canUserJoinCallUserIDReceivedUserID: String? + var canUserJoinCallUserIDReceivedInvocations: [String] = [] - var nextPageUnderlyingReturnValue: Result! - var nextPageReturnValue: Result! { + var canUserJoinCallUserIDUnderlyingReturnValue: Result! + var canUserJoinCallUserIDReturnValue: Result! { get { if Thread.isMainThread { - return nextPageUnderlyingReturnValue + return canUserJoinCallUserIDUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = nextPageUnderlyingReturnValue + returnValue = canUserJoinCallUserIDUnderlyingReturnValue } return returnValue! @@ -8171,229 +8149,508 @@ class RoomDirectorySearchProxyMock: RoomDirectorySearchProxyProtocol { } set { if Thread.isMainThread { - nextPageUnderlyingReturnValue = newValue + canUserJoinCallUserIDUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - nextPageUnderlyingReturnValue = newValue + canUserJoinCallUserIDUnderlyingReturnValue = newValue } } } } - var nextPageClosure: (() async -> Result)? + var canUserJoinCallUserIDClosure: ((String) async -> Result)? - func nextPage() async -> Result { - nextPageCallsCount += 1 - if let nextPageClosure = nextPageClosure { - return await nextPageClosure() + func canUserJoinCall(userID: String) async -> Result { + canUserJoinCallUserIDCallsCount += 1 + canUserJoinCallUserIDReceivedUserID = userID + DispatchQueue.main.async { + self.canUserJoinCallUserIDReceivedInvocations.append(userID) + } + if let canUserJoinCallUserIDClosure = canUserJoinCallUserIDClosure { + return await canUserJoinCallUserIDClosure(userID) } else { - return nextPageReturnValue + return canUserJoinCallUserIDReturnValue } } -} -class RoomMemberProxyMock: RoomMemberProxyProtocol { - var userID: String { - get { return underlyingUserID } - set(value) { underlyingUserID = value } - } - var underlyingUserID: String! - var displayName: String? - var avatarURL: URL? - var membership: MembershipState { - get { return underlyingMembership } - set(value) { underlyingMembership = value } - } - var underlyingMembership: MembershipState! - var isIgnored: Bool { - get { return underlyingIsIgnored } - set(value) { underlyingIsIgnored = value } - } - var underlyingIsIgnored: Bool! - var powerLevel: Int { - get { return underlyingPowerLevel } - set(value) { underlyingPowerLevel = value } - } - var underlyingPowerLevel: Int! - var role: RoomMemberRole { - get { return underlyingRole } - set(value) { underlyingRole = value } - } - var underlyingRole: RoomMemberRole! + //MARK: - elementCallWidgetDriver -} -class RoomNotificationSettingsProxyMock: RoomNotificationSettingsProxyProtocol { - var mode: RoomNotificationModeProxy { - get { return underlyingMode } - set(value) { underlyingMode = value } - } - var underlyingMode: RoomNotificationModeProxy! - var isDefault: Bool { - get { return underlyingIsDefault } - set(value) { underlyingIsDefault = value } - } - var underlyingIsDefault: Bool! + var elementCallWidgetDriverDeviceIDUnderlyingCallsCount = 0 + var elementCallWidgetDriverDeviceIDCallsCount: Int { + get { + if Thread.isMainThread { + return elementCallWidgetDriverDeviceIDUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = elementCallWidgetDriverDeviceIDUnderlyingCallsCount + } -} -class RoomProxyMock: RoomProxyProtocol { - var id: String { - get { return underlyingId } - set(value) { underlyingId = value } - } - var underlyingId: String! - var isDirect: Bool { - get { return underlyingIsDirect } - set(value) { underlyingIsDirect = value } - } - var underlyingIsDirect: Bool! - var isPublic: Bool { - get { return underlyingIsPublic } - set(value) { underlyingIsPublic = value } + return returnValue! + } + } + set { + if Thread.isMainThread { + elementCallWidgetDriverDeviceIDUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + elementCallWidgetDriverDeviceIDUnderlyingCallsCount = newValue + } + } + } } - var underlyingIsPublic: Bool! - var isSpace: Bool { - get { return underlyingIsSpace } - set(value) { underlyingIsSpace = value } + var elementCallWidgetDriverDeviceIDCalled: Bool { + return elementCallWidgetDriverDeviceIDCallsCount > 0 } - var underlyingIsSpace: Bool! - var isEncrypted: Bool { - get { return underlyingIsEncrypted } - set(value) { underlyingIsEncrypted = value } + var elementCallWidgetDriverDeviceIDReceivedDeviceID: String? + var elementCallWidgetDriverDeviceIDReceivedInvocations: [String] = [] + + var elementCallWidgetDriverDeviceIDUnderlyingReturnValue: ElementCallWidgetDriverProtocol! + var elementCallWidgetDriverDeviceIDReturnValue: ElementCallWidgetDriverProtocol! { + get { + if Thread.isMainThread { + return elementCallWidgetDriverDeviceIDUnderlyingReturnValue + } else { + var returnValue: ElementCallWidgetDriverProtocol? = nil + DispatchQueue.main.sync { + returnValue = elementCallWidgetDriverDeviceIDUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + elementCallWidgetDriverDeviceIDUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + elementCallWidgetDriverDeviceIDUnderlyingReturnValue = newValue + } + } + } } - var underlyingIsEncrypted: Bool! - var isFavouriteCallsCount = 0 - var isFavouriteCalled: Bool { - return isFavouriteCallsCount > 0 + var elementCallWidgetDriverDeviceIDClosure: ((String) -> ElementCallWidgetDriverProtocol)? + + func elementCallWidgetDriver(deviceID: String) -> ElementCallWidgetDriverProtocol { + elementCallWidgetDriverDeviceIDCallsCount += 1 + elementCallWidgetDriverDeviceIDReceivedDeviceID = deviceID + DispatchQueue.main.async { + self.elementCallWidgetDriverDeviceIDReceivedInvocations.append(deviceID) + } + if let elementCallWidgetDriverDeviceIDClosure = elementCallWidgetDriverDeviceIDClosure { + return elementCallWidgetDriverDeviceIDClosure(deviceID) + } else { + return elementCallWidgetDriverDeviceIDReturnValue + } } + //MARK: - sendCallNotificationIfNeeded - var isFavourite: Bool { - get async { - isFavouriteCallsCount += 1 - if let isFavouriteClosure = isFavouriteClosure { - return await isFavouriteClosure() + var sendCallNotificationIfNeededUnderlyingCallsCount = 0 + var sendCallNotificationIfNeededCallsCount: Int { + get { + if Thread.isMainThread { + return sendCallNotificationIfNeededUnderlyingCallsCount } else { - return underlyingIsFavourite + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = sendCallNotificationIfNeededUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + sendCallNotificationIfNeededUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + sendCallNotificationIfNeededUnderlyingCallsCount = newValue + } } } } - var underlyingIsFavourite: Bool! - var isFavouriteClosure: (() async -> Bool)? - var pinnedEventIDsCallsCount = 0 - var pinnedEventIDsCalled: Bool { - return pinnedEventIDsCallsCount > 0 + var sendCallNotificationIfNeededCalled: Bool { + return sendCallNotificationIfNeededCallsCount > 0 } - var pinnedEventIDs: Set { - get async { - pinnedEventIDsCallsCount += 1 - if let pinnedEventIDsClosure = pinnedEventIDsClosure { - return await pinnedEventIDsClosure() + var sendCallNotificationIfNeededUnderlyingReturnValue: Result! + var sendCallNotificationIfNeededReturnValue: Result! { + get { + if Thread.isMainThread { + return sendCallNotificationIfNeededUnderlyingReturnValue } else { - return underlyingPinnedEventIDs + var returnValue: Result? = nil + DispatchQueue.main.sync { + returnValue = sendCallNotificationIfNeededUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + sendCallNotificationIfNeededUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + sendCallNotificationIfNeededUnderlyingReturnValue = newValue + } } } } - var underlyingPinnedEventIDs: Set! - var pinnedEventIDsClosure: (() async -> Set)? - var membership: Membership { - get { return underlyingMembership } - set(value) { underlyingMembership = value } - } - var underlyingMembership: Membership! - var inviterCallsCount = 0 - var inviterCalled: Bool { - return inviterCallsCount > 0 + var sendCallNotificationIfNeededClosure: (() async -> Result)? + + func sendCallNotificationIfNeeded() async -> Result { + sendCallNotificationIfNeededCallsCount += 1 + if let sendCallNotificationIfNeededClosure = sendCallNotificationIfNeededClosure { + return await sendCallNotificationIfNeededClosure() + } else { + return sendCallNotificationIfNeededReturnValue + } } + //MARK: - matrixToPermalink - var inviter: RoomMemberProxyProtocol? { - get async { - inviterCallsCount += 1 - if let inviterClosure = inviterClosure { - return await inviterClosure() + var matrixToPermalinkUnderlyingCallsCount = 0 + var matrixToPermalinkCallsCount: Int { + get { + if Thread.isMainThread { + return matrixToPermalinkUnderlyingCallsCount } else { - return underlyingInviter + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = matrixToPermalinkUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + matrixToPermalinkUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + matrixToPermalinkUnderlyingCallsCount = newValue + } } } } - var underlyingInviter: RoomMemberProxyProtocol? - var inviterClosure: (() async -> RoomMemberProxyProtocol?)? - var hasOngoingCall: Bool { - get { return underlyingHasOngoingCall } - set(value) { underlyingHasOngoingCall = value } + var matrixToPermalinkCalled: Bool { + return matrixToPermalinkCallsCount > 0 } - var underlyingHasOngoingCall: Bool! - var activeRoomCallParticipants: [String] = [] - var canonicalAlias: String? - var ownUserID: String { - get { return underlyingOwnUserID } - set(value) { underlyingOwnUserID = value } + + var matrixToPermalinkUnderlyingReturnValue: Result! + var matrixToPermalinkReturnValue: Result! { + get { + if Thread.isMainThread { + return matrixToPermalinkUnderlyingReturnValue + } else { + var returnValue: Result? = nil + DispatchQueue.main.sync { + returnValue = matrixToPermalinkUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + matrixToPermalinkUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + matrixToPermalinkUnderlyingReturnValue = newValue + } + } + } } - var underlyingOwnUserID: String! - var name: String? - var topic: String? - var avatar: RoomAvatar { - get { return underlyingAvatar } - set(value) { underlyingAvatar = value } + var matrixToPermalinkClosure: (() async -> Result)? + + func matrixToPermalink() async -> Result { + matrixToPermalinkCallsCount += 1 + if let matrixToPermalinkClosure = matrixToPermalinkClosure { + return await matrixToPermalinkClosure() + } else { + return matrixToPermalinkReturnValue + } } - var underlyingAvatar: RoomAvatar! - var avatarURL: URL? - var membersPublisher: CurrentValuePublisher<[RoomMemberProxyProtocol], Never> { - get { return underlyingMembersPublisher } - set(value) { underlyingMembersPublisher = value } + //MARK: - matrixToEventPermalink + + var matrixToEventPermalinkUnderlyingCallsCount = 0 + var matrixToEventPermalinkCallsCount: Int { + get { + if Thread.isMainThread { + return matrixToEventPermalinkUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = matrixToEventPermalinkUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + matrixToEventPermalinkUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + matrixToEventPermalinkUnderlyingCallsCount = newValue + } + } + } } - var underlyingMembersPublisher: CurrentValuePublisher<[RoomMemberProxyProtocol], Never>! - var typingMembersPublisher: CurrentValuePublisher<[String], Never> { - get { return underlyingTypingMembersPublisher } - set(value) { underlyingTypingMembersPublisher = value } + var matrixToEventPermalinkCalled: Bool { + return matrixToEventPermalinkCallsCount > 0 } - var underlyingTypingMembersPublisher: CurrentValuePublisher<[String], Never>! - var joinedMembersCount: Int { - get { return underlyingJoinedMembersCount } - set(value) { underlyingJoinedMembersCount = value } + var matrixToEventPermalinkReceivedEventID: String? + var matrixToEventPermalinkReceivedInvocations: [String] = [] + + var matrixToEventPermalinkUnderlyingReturnValue: Result! + var matrixToEventPermalinkReturnValue: Result! { + get { + if Thread.isMainThread { + return matrixToEventPermalinkUnderlyingReturnValue + } else { + var returnValue: Result? = nil + DispatchQueue.main.sync { + returnValue = matrixToEventPermalinkUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + matrixToEventPermalinkUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + matrixToEventPermalinkUnderlyingReturnValue = newValue + } + } + } } - var underlyingJoinedMembersCount: Int! - var activeMembersCount: Int { - get { return underlyingActiveMembersCount } - set(value) { underlyingActiveMembersCount = value } + var matrixToEventPermalinkClosure: ((String) async -> Result)? + + func matrixToEventPermalink(_ eventID: String) async -> Result { + matrixToEventPermalinkCallsCount += 1 + matrixToEventPermalinkReceivedEventID = eventID + DispatchQueue.main.async { + self.matrixToEventPermalinkReceivedInvocations.append(eventID) + } + if let matrixToEventPermalinkClosure = matrixToEventPermalinkClosure { + return await matrixToEventPermalinkClosure(eventID) + } else { + return matrixToEventPermalinkReturnValue + } } - var underlyingActiveMembersCount: Int! - var actionsPublisher: AnyPublisher { - get { return underlyingActionsPublisher } - set(value) { underlyingActionsPublisher = value } + //MARK: - saveDraft + + var saveDraftUnderlyingCallsCount = 0 + var saveDraftCallsCount: Int { + get { + if Thread.isMainThread { + return saveDraftUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = saveDraftUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + saveDraftUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + saveDraftUnderlyingCallsCount = newValue + } + } + } } - var underlyingActionsPublisher: AnyPublisher! - var timeline: TimelineProxyProtocol { - get { return underlyingTimeline } - set(value) { underlyingTimeline = value } + var saveDraftCalled: Bool { + return saveDraftCallsCount > 0 } - var underlyingTimeline: TimelineProxyProtocol! - var pinnedEventsTimelineCallsCount = 0 - var pinnedEventsTimelineCalled: Bool { - return pinnedEventsTimelineCallsCount > 0 + var saveDraftReceivedDraft: ComposerDraft? + var saveDraftReceivedInvocations: [ComposerDraft] = [] + + var saveDraftUnderlyingReturnValue: Result! + var saveDraftReturnValue: Result! { + get { + if Thread.isMainThread { + return saveDraftUnderlyingReturnValue + } else { + var returnValue: Result? = nil + DispatchQueue.main.sync { + returnValue = saveDraftUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + saveDraftUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + saveDraftUnderlyingReturnValue = newValue + } + } + } } + var saveDraftClosure: ((ComposerDraft) async -> Result)? - var pinnedEventsTimeline: TimelineProxyProtocol? { - get async { - pinnedEventsTimelineCallsCount += 1 - if let pinnedEventsTimelineClosure = pinnedEventsTimelineClosure { - return await pinnedEventsTimelineClosure() + func saveDraft(_ draft: ComposerDraft) async -> Result { + saveDraftCallsCount += 1 + saveDraftReceivedDraft = draft + DispatchQueue.main.async { + self.saveDraftReceivedInvocations.append(draft) + } + if let saveDraftClosure = saveDraftClosure { + return await saveDraftClosure(draft) + } else { + return saveDraftReturnValue + } + } + //MARK: - loadDraft + + var loadDraftUnderlyingCallsCount = 0 + var loadDraftCallsCount: Int { + get { + if Thread.isMainThread { + return loadDraftUnderlyingCallsCount } else { - return underlyingPinnedEventsTimeline + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = loadDraftUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + loadDraftUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + loadDraftUnderlyingCallsCount = newValue + } + } + } + } + var loadDraftCalled: Bool { + return loadDraftCallsCount > 0 + } + + var loadDraftUnderlyingReturnValue: Result! + var loadDraftReturnValue: Result! { + get { + if Thread.isMainThread { + return loadDraftUnderlyingReturnValue + } else { + var returnValue: Result? = nil + DispatchQueue.main.sync { + returnValue = loadDraftUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + loadDraftUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + loadDraftUnderlyingReturnValue = newValue + } + } + } + } + var loadDraftClosure: (() async -> Result)? + + func loadDraft() async -> Result { + loadDraftCallsCount += 1 + if let loadDraftClosure = loadDraftClosure { + return await loadDraftClosure() + } else { + return loadDraftReturnValue + } + } + //MARK: - clearDraft + + var clearDraftUnderlyingCallsCount = 0 + var clearDraftCallsCount: Int { + get { + if Thread.isMainThread { + return clearDraftUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = clearDraftUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + clearDraftUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + clearDraftUnderlyingCallsCount = newValue + } + } + } + } + var clearDraftCalled: Bool { + return clearDraftCallsCount > 0 + } + + var clearDraftUnderlyingReturnValue: Result! + var clearDraftReturnValue: Result! { + get { + if Thread.isMainThread { + return clearDraftUnderlyingReturnValue + } else { + var returnValue: Result? = nil + DispatchQueue.main.sync { + returnValue = clearDraftUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + clearDraftUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + clearDraftUnderlyingReturnValue = newValue + } } } } - var underlyingPinnedEventsTimeline: TimelineProxyProtocol? - var pinnedEventsTimelineClosure: (() async -> TimelineProxyProtocol?)? + var clearDraftClosure: (() async -> Result)? - //MARK: - subscribeForUpdates + func clearDraft() async -> Result { + clearDraftCallsCount += 1 + if let clearDraftClosure = clearDraftClosure { + return await clearDraftClosure() + } else { + return clearDraftReturnValue + } + } +} +class KeychainControllerMock: KeychainControllerProtocol { - var subscribeForUpdatesUnderlyingCallsCount = 0 - var subscribeForUpdatesCallsCount: Int { + //MARK: - setRestorationToken + + var setRestorationTokenForUsernameUnderlyingCallsCount = 0 + var setRestorationTokenForUsernameCallsCount: Int { get { if Thread.isMainThread { - return subscribeForUpdatesUnderlyingCallsCount + return setRestorationTokenForUsernameUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = subscribeForUpdatesUnderlyingCallsCount + returnValue = setRestorationTokenForUsernameUnderlyingCallsCount } return returnValue! @@ -8401,34 +8658,40 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - subscribeForUpdatesUnderlyingCallsCount = newValue + setRestorationTokenForUsernameUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - subscribeForUpdatesUnderlyingCallsCount = newValue + setRestorationTokenForUsernameUnderlyingCallsCount = newValue } } } } - var subscribeForUpdatesCalled: Bool { - return subscribeForUpdatesCallsCount > 0 + var setRestorationTokenForUsernameCalled: Bool { + return setRestorationTokenForUsernameCallsCount > 0 } - var subscribeForUpdatesClosure: (() async -> Void)? + var setRestorationTokenForUsernameReceivedArguments: (restorationToken: RestorationToken, forUsername: String)? + var setRestorationTokenForUsernameReceivedInvocations: [(restorationToken: RestorationToken, forUsername: String)] = [] + var setRestorationTokenForUsernameClosure: ((RestorationToken, String) -> Void)? - func subscribeForUpdates() async { - subscribeForUpdatesCallsCount += 1 - await subscribeForUpdatesClosure?() + func setRestorationToken(_ restorationToken: RestorationToken, forUsername: String) { + setRestorationTokenForUsernameCallsCount += 1 + setRestorationTokenForUsernameReceivedArguments = (restorationToken: restorationToken, forUsername: forUsername) + DispatchQueue.main.async { + self.setRestorationTokenForUsernameReceivedInvocations.append((restorationToken: restorationToken, forUsername: forUsername)) + } + setRestorationTokenForUsernameClosure?(restorationToken, forUsername) } - //MARK: - subscribeToRoomInfoUpdates + //MARK: - restorationTokens - var subscribeToRoomInfoUpdatesUnderlyingCallsCount = 0 - var subscribeToRoomInfoUpdatesCallsCount: Int { + var restorationTokensUnderlyingCallsCount = 0 + var restorationTokensCallsCount: Int { get { if Thread.isMainThread { - return subscribeToRoomInfoUpdatesUnderlyingCallsCount + return restorationTokensUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = subscribeToRoomInfoUpdatesUnderlyingCallsCount + returnValue = restorationTokensUnderlyingCallsCount } return returnValue! @@ -8436,34 +8699,63 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - subscribeToRoomInfoUpdatesUnderlyingCallsCount = newValue + restorationTokensUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - subscribeToRoomInfoUpdatesUnderlyingCallsCount = newValue + restorationTokensUnderlyingCallsCount = newValue } } } } - var subscribeToRoomInfoUpdatesCalled: Bool { - return subscribeToRoomInfoUpdatesCallsCount > 0 + var restorationTokensCalled: Bool { + return restorationTokensCallsCount > 0 } - var subscribeToRoomInfoUpdatesClosure: (() -> Void)? - func subscribeToRoomInfoUpdates() { - subscribeToRoomInfoUpdatesCallsCount += 1 - subscribeToRoomInfoUpdatesClosure?() + var restorationTokensUnderlyingReturnValue: [KeychainCredentials]! + var restorationTokensReturnValue: [KeychainCredentials]! { + get { + if Thread.isMainThread { + return restorationTokensUnderlyingReturnValue + } else { + var returnValue: [KeychainCredentials]? = nil + DispatchQueue.main.sync { + returnValue = restorationTokensUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + restorationTokensUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + restorationTokensUnderlyingReturnValue = newValue + } + } + } } - //MARK: - timelineFocusedOnEvent + var restorationTokensClosure: (() -> [KeychainCredentials])? - var timelineFocusedOnEventEventIDNumberOfEventsUnderlyingCallsCount = 0 - var timelineFocusedOnEventEventIDNumberOfEventsCallsCount: Int { + func restorationTokens() -> [KeychainCredentials] { + restorationTokensCallsCount += 1 + if let restorationTokensClosure = restorationTokensClosure { + return restorationTokensClosure() + } else { + return restorationTokensReturnValue + } + } + //MARK: - removeRestorationTokenForUsername + + var removeRestorationTokenForUsernameUnderlyingCallsCount = 0 + var removeRestorationTokenForUsernameCallsCount: Int { get { if Thread.isMainThread { - return timelineFocusedOnEventEventIDNumberOfEventsUnderlyingCallsCount + return removeRestorationTokenForUsernameUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = timelineFocusedOnEventEventIDNumberOfEventsUnderlyingCallsCount + returnValue = removeRestorationTokenForUsernameUnderlyingCallsCount } return returnValue! @@ -8471,29 +8763,40 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - timelineFocusedOnEventEventIDNumberOfEventsUnderlyingCallsCount = newValue + removeRestorationTokenForUsernameUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - timelineFocusedOnEventEventIDNumberOfEventsUnderlyingCallsCount = newValue + removeRestorationTokenForUsernameUnderlyingCallsCount = newValue } } } } - var timelineFocusedOnEventEventIDNumberOfEventsCalled: Bool { - return timelineFocusedOnEventEventIDNumberOfEventsCallsCount > 0 + var removeRestorationTokenForUsernameCalled: Bool { + return removeRestorationTokenForUsernameCallsCount > 0 } - var timelineFocusedOnEventEventIDNumberOfEventsReceivedArguments: (eventID: String, numberOfEvents: UInt16)? - var timelineFocusedOnEventEventIDNumberOfEventsReceivedInvocations: [(eventID: String, numberOfEvents: UInt16)] = [] + var removeRestorationTokenForUsernameReceivedUsername: String? + var removeRestorationTokenForUsernameReceivedInvocations: [String] = [] + var removeRestorationTokenForUsernameClosure: ((String) -> Void)? - var timelineFocusedOnEventEventIDNumberOfEventsUnderlyingReturnValue: Result! - var timelineFocusedOnEventEventIDNumberOfEventsReturnValue: Result! { + func removeRestorationTokenForUsername(_ username: String) { + removeRestorationTokenForUsernameCallsCount += 1 + removeRestorationTokenForUsernameReceivedUsername = username + DispatchQueue.main.async { + self.removeRestorationTokenForUsernameReceivedInvocations.append(username) + } + removeRestorationTokenForUsernameClosure?(username) + } + //MARK: - removeAllRestorationTokens + + var removeAllRestorationTokensUnderlyingCallsCount = 0 + var removeAllRestorationTokensCallsCount: Int { get { if Thread.isMainThread { - return timelineFocusedOnEventEventIDNumberOfEventsUnderlyingReturnValue + return removeAllRestorationTokensUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = timelineFocusedOnEventEventIDNumberOfEventsUnderlyingReturnValue + returnValue = removeAllRestorationTokensUnderlyingCallsCount } return returnValue! @@ -8501,39 +8804,63 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - timelineFocusedOnEventEventIDNumberOfEventsUnderlyingReturnValue = newValue + removeAllRestorationTokensUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - timelineFocusedOnEventEventIDNumberOfEventsUnderlyingReturnValue = newValue + removeAllRestorationTokensUnderlyingCallsCount = newValue } } } } - var timelineFocusedOnEventEventIDNumberOfEventsClosure: ((String, UInt16) async -> Result)? + var removeAllRestorationTokensCalled: Bool { + return removeAllRestorationTokensCallsCount > 0 + } + var removeAllRestorationTokensClosure: (() -> Void)? - func timelineFocusedOnEvent(eventID: String, numberOfEvents: UInt16) async -> Result { - timelineFocusedOnEventEventIDNumberOfEventsCallsCount += 1 - timelineFocusedOnEventEventIDNumberOfEventsReceivedArguments = (eventID: eventID, numberOfEvents: numberOfEvents) - DispatchQueue.main.async { - self.timelineFocusedOnEventEventIDNumberOfEventsReceivedInvocations.append((eventID: eventID, numberOfEvents: numberOfEvents)) + func removeAllRestorationTokens() { + removeAllRestorationTokensCallsCount += 1 + removeAllRestorationTokensClosure?() + } + //MARK: - containsPINCode + + var containsPINCodeThrowableError: Error? + var containsPINCodeUnderlyingCallsCount = 0 + var containsPINCodeCallsCount: Int { + get { + if Thread.isMainThread { + return containsPINCodeUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = containsPINCodeUnderlyingCallsCount + } + + return returnValue! + } } - if let timelineFocusedOnEventEventIDNumberOfEventsClosure = timelineFocusedOnEventEventIDNumberOfEventsClosure { - return await timelineFocusedOnEventEventIDNumberOfEventsClosure(eventID, numberOfEvents) - } else { - return timelineFocusedOnEventEventIDNumberOfEventsReturnValue + set { + if Thread.isMainThread { + containsPINCodeUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + containsPINCodeUnderlyingCallsCount = newValue + } + } } } - //MARK: - redact + var containsPINCodeCalled: Bool { + return containsPINCodeCallsCount > 0 + } - var redactUnderlyingCallsCount = 0 - var redactCallsCount: Int { + var containsPINCodeUnderlyingReturnValue: Bool! + var containsPINCodeReturnValue: Bool! { get { if Thread.isMainThread { - return redactUnderlyingCallsCount + return containsPINCodeUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Bool? = nil DispatchQueue.main.sync { - returnValue = redactUnderlyingCallsCount + returnValue = containsPINCodeUnderlyingReturnValue } return returnValue! @@ -8541,29 +8868,39 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - redactUnderlyingCallsCount = newValue + containsPINCodeUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - redactUnderlyingCallsCount = newValue + containsPINCodeUnderlyingReturnValue = newValue } } } } - var redactCalled: Bool { - return redactCallsCount > 0 + var containsPINCodeClosure: (() throws -> Bool)? + + func containsPINCode() throws -> Bool { + if let error = containsPINCodeThrowableError { + throw error + } + containsPINCodeCallsCount += 1 + if let containsPINCodeClosure = containsPINCodeClosure { + return try containsPINCodeClosure() + } else { + return containsPINCodeReturnValue + } } - var redactReceivedEventID: String? - var redactReceivedInvocations: [String] = [] + //MARK: - setPINCode - var redactUnderlyingReturnValue: Result! - var redactReturnValue: Result! { + var setPINCodeThrowableError: Error? + var setPINCodeUnderlyingCallsCount = 0 + var setPINCodeCallsCount: Int { get { if Thread.isMainThread { - return redactUnderlyingReturnValue + return setPINCodeUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = redactUnderlyingReturnValue + returnValue = setPINCodeUnderlyingCallsCount } return returnValue! @@ -8571,39 +8908,43 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - redactUnderlyingReturnValue = newValue + setPINCodeUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - redactUnderlyingReturnValue = newValue + setPINCodeUnderlyingCallsCount = newValue } } } } - var redactClosure: ((String) async -> Result)? + var setPINCodeCalled: Bool { + return setPINCodeCallsCount > 0 + } + var setPINCodeReceivedPinCode: String? + var setPINCodeReceivedInvocations: [String] = [] + var setPINCodeClosure: ((String) throws -> Void)? - func redact(_ eventID: String) async -> Result { - redactCallsCount += 1 - redactReceivedEventID = eventID + func setPINCode(_ pinCode: String) throws { + if let error = setPINCodeThrowableError { + throw error + } + setPINCodeCallsCount += 1 + setPINCodeReceivedPinCode = pinCode DispatchQueue.main.async { - self.redactReceivedInvocations.append(eventID) - } - if let redactClosure = redactClosure { - return await redactClosure(eventID) - } else { - return redactReturnValue + self.setPINCodeReceivedInvocations.append(pinCode) } + try setPINCodeClosure?(pinCode) } - //MARK: - reportContent + //MARK: - pinCode - var reportContentReasonUnderlyingCallsCount = 0 - var reportContentReasonCallsCount: Int { + var pinCodeUnderlyingCallsCount = 0 + var pinCodeCallsCount: Int { get { if Thread.isMainThread { - return reportContentReasonUnderlyingCallsCount + return pinCodeUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = reportContentReasonUnderlyingCallsCount + returnValue = pinCodeUnderlyingCallsCount } return returnValue! @@ -8611,29 +8952,27 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - reportContentReasonUnderlyingCallsCount = newValue + pinCodeUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - reportContentReasonUnderlyingCallsCount = newValue + pinCodeUnderlyingCallsCount = newValue } } } } - var reportContentReasonCalled: Bool { - return reportContentReasonCallsCount > 0 + var pinCodeCalled: Bool { + return pinCodeCallsCount > 0 } - var reportContentReasonReceivedArguments: (eventID: String, reason: String?)? - var reportContentReasonReceivedInvocations: [(eventID: String, reason: String?)] = [] - var reportContentReasonUnderlyingReturnValue: Result! - var reportContentReasonReturnValue: Result! { + var pinCodeUnderlyingReturnValue: String? + var pinCodeReturnValue: String? { get { if Thread.isMainThread { - return reportContentReasonUnderlyingReturnValue + return pinCodeUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: String?? = nil DispatchQueue.main.sync { - returnValue = reportContentReasonUnderlyingReturnValue + returnValue = pinCodeUnderlyingReturnValue } return returnValue! @@ -8641,39 +8980,35 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - reportContentReasonUnderlyingReturnValue = newValue + pinCodeUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - reportContentReasonUnderlyingReturnValue = newValue + pinCodeUnderlyingReturnValue = newValue } } } } - var reportContentReasonClosure: ((String, String?) async -> Result)? + var pinCodeClosure: (() -> String?)? - func reportContent(_ eventID: String, reason: String?) async -> Result { - reportContentReasonCallsCount += 1 - reportContentReasonReceivedArguments = (eventID: eventID, reason: reason) - DispatchQueue.main.async { - self.reportContentReasonReceivedInvocations.append((eventID: eventID, reason: reason)) - } - if let reportContentReasonClosure = reportContentReasonClosure { - return await reportContentReasonClosure(eventID, reason) + func pinCode() -> String? { + pinCodeCallsCount += 1 + if let pinCodeClosure = pinCodeClosure { + return pinCodeClosure() } else { - return reportContentReasonReturnValue + return pinCodeReturnValue } } - //MARK: - leaveRoom + //MARK: - removePINCode - var leaveRoomUnderlyingCallsCount = 0 - var leaveRoomCallsCount: Int { + var removePINCodeUnderlyingCallsCount = 0 + var removePINCodeCallsCount: Int { get { if Thread.isMainThread { - return leaveRoomUnderlyingCallsCount + return removePINCodeUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = leaveRoomUnderlyingCallsCount + returnValue = removePINCodeUnderlyingCallsCount } return returnValue! @@ -8681,27 +9016,34 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - leaveRoomUnderlyingCallsCount = newValue + removePINCodeUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - leaveRoomUnderlyingCallsCount = newValue + removePINCodeUnderlyingCallsCount = newValue } } } } - var leaveRoomCalled: Bool { - return leaveRoomCallsCount > 0 + var removePINCodeCalled: Bool { + return removePINCodeCallsCount > 0 } + var removePINCodeClosure: (() -> Void)? - var leaveRoomUnderlyingReturnValue: Result! - var leaveRoomReturnValue: Result! { + func removePINCode() { + removePINCodeCallsCount += 1 + removePINCodeClosure?() + } + //MARK: - containsPINCodeBiometricState + + var containsPINCodeBiometricStateUnderlyingCallsCount = 0 + var containsPINCodeBiometricStateCallsCount: Int { get { if Thread.isMainThread { - return leaveRoomUnderlyingReturnValue + return containsPINCodeBiometricStateUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = leaveRoomUnderlyingReturnValue + returnValue = containsPINCodeBiometricStateUnderlyingCallsCount } return returnValue! @@ -8709,35 +9051,27 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - leaveRoomUnderlyingReturnValue = newValue + containsPINCodeBiometricStateUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - leaveRoomUnderlyingReturnValue = newValue + containsPINCodeBiometricStateUnderlyingCallsCount = newValue } } } } - var leaveRoomClosure: (() async -> Result)? - - func leaveRoom() async -> Result { - leaveRoomCallsCount += 1 - if let leaveRoomClosure = leaveRoomClosure { - return await leaveRoomClosure() - } else { - return leaveRoomReturnValue - } + var containsPINCodeBiometricStateCalled: Bool { + return containsPINCodeBiometricStateCallsCount > 0 } - //MARK: - updateMembers - var updateMembersUnderlyingCallsCount = 0 - var updateMembersCallsCount: Int { + var containsPINCodeBiometricStateUnderlyingReturnValue: Bool! + var containsPINCodeBiometricStateReturnValue: Bool! { get { if Thread.isMainThread { - return updateMembersUnderlyingCallsCount + return containsPINCodeBiometricStateUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Bool? = nil DispatchQueue.main.sync { - returnValue = updateMembersUnderlyingCallsCount + returnValue = containsPINCodeBiometricStateUnderlyingReturnValue } return returnValue! @@ -8745,34 +9079,36 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - updateMembersUnderlyingCallsCount = newValue + containsPINCodeBiometricStateUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - updateMembersUnderlyingCallsCount = newValue + containsPINCodeBiometricStateUnderlyingReturnValue = newValue } } } } - var updateMembersCalled: Bool { - return updateMembersCallsCount > 0 - } - var updateMembersClosure: (() async -> Void)? + var containsPINCodeBiometricStateClosure: (() -> Bool)? - func updateMembers() async { - updateMembersCallsCount += 1 - await updateMembersClosure?() + func containsPINCodeBiometricState() -> Bool { + containsPINCodeBiometricStateCallsCount += 1 + if let containsPINCodeBiometricStateClosure = containsPINCodeBiometricStateClosure { + return containsPINCodeBiometricStateClosure() + } else { + return containsPINCodeBiometricStateReturnValue + } } - //MARK: - getMember + //MARK: - setPINCodeBiometricState - var getMemberUserIDUnderlyingCallsCount = 0 - var getMemberUserIDCallsCount: Int { + var setPINCodeBiometricStateThrowableError: Error? + var setPINCodeBiometricStateUnderlyingCallsCount = 0 + var setPINCodeBiometricStateCallsCount: Int { get { if Thread.isMainThread { - return getMemberUserIDUnderlyingCallsCount + return setPINCodeBiometricStateUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = getMemberUserIDUnderlyingCallsCount + returnValue = setPINCodeBiometricStateUnderlyingCallsCount } return returnValue! @@ -8780,29 +9116,43 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - getMemberUserIDUnderlyingCallsCount = newValue + setPINCodeBiometricStateUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - getMemberUserIDUnderlyingCallsCount = newValue + setPINCodeBiometricStateUnderlyingCallsCount = newValue } } } } - var getMemberUserIDCalled: Bool { - return getMemberUserIDCallsCount > 0 + var setPINCodeBiometricStateCalled: Bool { + return setPINCodeBiometricStateCallsCount > 0 } - var getMemberUserIDReceivedUserID: String? - var getMemberUserIDReceivedInvocations: [String] = [] + var setPINCodeBiometricStateReceivedState: Data? + var setPINCodeBiometricStateReceivedInvocations: [Data] = [] + var setPINCodeBiometricStateClosure: ((Data) throws -> Void)? - var getMemberUserIDUnderlyingReturnValue: Result! - var getMemberUserIDReturnValue: Result! { + func setPINCodeBiometricState(_ state: Data) throws { + if let error = setPINCodeBiometricStateThrowableError { + throw error + } + setPINCodeBiometricStateCallsCount += 1 + setPINCodeBiometricStateReceivedState = state + DispatchQueue.main.async { + self.setPINCodeBiometricStateReceivedInvocations.append(state) + } + try setPINCodeBiometricStateClosure?(state) + } + //MARK: - pinCodeBiometricState + + var pinCodeBiometricStateUnderlyingCallsCount = 0 + var pinCodeBiometricStateCallsCount: Int { get { if Thread.isMainThread { - return getMemberUserIDUnderlyingReturnValue + return pinCodeBiometricStateUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = getMemberUserIDUnderlyingReturnValue + returnValue = pinCodeBiometricStateUnderlyingCallsCount } return returnValue! @@ -8810,39 +9160,27 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - getMemberUserIDUnderlyingReturnValue = newValue + pinCodeBiometricStateUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - getMemberUserIDUnderlyingReturnValue = newValue + pinCodeBiometricStateUnderlyingCallsCount = newValue } } } } - var getMemberUserIDClosure: ((String) async -> Result)? - - func getMember(userID: String) async -> Result { - getMemberUserIDCallsCount += 1 - getMemberUserIDReceivedUserID = userID - DispatchQueue.main.async { - self.getMemberUserIDReceivedInvocations.append(userID) - } - if let getMemberUserIDClosure = getMemberUserIDClosure { - return await getMemberUserIDClosure(userID) - } else { - return getMemberUserIDReturnValue - } + var pinCodeBiometricStateCalled: Bool { + return pinCodeBiometricStateCallsCount > 0 } - //MARK: - rejectInvitation - var rejectInvitationUnderlyingCallsCount = 0 - var rejectInvitationCallsCount: Int { + var pinCodeBiometricStateUnderlyingReturnValue: Data? + var pinCodeBiometricStateReturnValue: Data? { get { if Thread.isMainThread { - return rejectInvitationUnderlyingCallsCount + return pinCodeBiometricStateUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Data?? = nil DispatchQueue.main.sync { - returnValue = rejectInvitationUnderlyingCallsCount + returnValue = pinCodeBiometricStateUnderlyingReturnValue } return returnValue! @@ -8850,27 +9188,35 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - rejectInvitationUnderlyingCallsCount = newValue + pinCodeBiometricStateUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - rejectInvitationUnderlyingCallsCount = newValue + pinCodeBiometricStateUnderlyingReturnValue = newValue } } } } - var rejectInvitationCalled: Bool { - return rejectInvitationCallsCount > 0 + var pinCodeBiometricStateClosure: (() -> Data?)? + + func pinCodeBiometricState() -> Data? { + pinCodeBiometricStateCallsCount += 1 + if let pinCodeBiometricStateClosure = pinCodeBiometricStateClosure { + return pinCodeBiometricStateClosure() + } else { + return pinCodeBiometricStateReturnValue + } } + //MARK: - removePINCodeBiometricState - var rejectInvitationUnderlyingReturnValue: Result! - var rejectInvitationReturnValue: Result! { + var removePINCodeBiometricStateUnderlyingCallsCount = 0 + var removePINCodeBiometricStateCallsCount: Int { get { if Thread.isMainThread { - return rejectInvitationUnderlyingReturnValue + return removePINCodeBiometricStateUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = rejectInvitationUnderlyingReturnValue + returnValue = removePINCodeBiometricStateUnderlyingCallsCount } return returnValue! @@ -8878,35 +9224,38 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - rejectInvitationUnderlyingReturnValue = newValue + removePINCodeBiometricStateUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - rejectInvitationUnderlyingReturnValue = newValue + removePINCodeBiometricStateUnderlyingCallsCount = newValue } } } } - var rejectInvitationClosure: (() async -> Result)? - - func rejectInvitation() async -> Result { - rejectInvitationCallsCount += 1 - if let rejectInvitationClosure = rejectInvitationClosure { - return await rejectInvitationClosure() - } else { - return rejectInvitationReturnValue - } + var removePINCodeBiometricStateCalled: Bool { + return removePINCodeBiometricStateCallsCount > 0 } - //MARK: - acceptInvitation + var removePINCodeBiometricStateClosure: (() -> Void)? - var acceptInvitationUnderlyingCallsCount = 0 - var acceptInvitationCallsCount: Int { + func removePINCodeBiometricState() { + removePINCodeBiometricStateCallsCount += 1 + removePINCodeBiometricStateClosure?() + } +} +class MediaLoaderMock: MediaLoaderProtocol { + + //MARK: - loadMediaContentForSource + + var loadMediaContentForSourceThrowableError: Error? + var loadMediaContentForSourceUnderlyingCallsCount = 0 + var loadMediaContentForSourceCallsCount: Int { get { if Thread.isMainThread { - return acceptInvitationUnderlyingCallsCount + return loadMediaContentForSourceUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = acceptInvitationUnderlyingCallsCount + returnValue = loadMediaContentForSourceUnderlyingCallsCount } return returnValue! @@ -8914,27 +9263,29 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - acceptInvitationUnderlyingCallsCount = newValue + loadMediaContentForSourceUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - acceptInvitationUnderlyingCallsCount = newValue + loadMediaContentForSourceUnderlyingCallsCount = newValue } } } } - var acceptInvitationCalled: Bool { - return acceptInvitationCallsCount > 0 + var loadMediaContentForSourceCalled: Bool { + return loadMediaContentForSourceCallsCount > 0 } + var loadMediaContentForSourceReceivedSource: MediaSourceProxy? + var loadMediaContentForSourceReceivedInvocations: [MediaSourceProxy] = [] - var acceptInvitationUnderlyingReturnValue: Result! - var acceptInvitationReturnValue: Result! { + var loadMediaContentForSourceUnderlyingReturnValue: Data! + var loadMediaContentForSourceReturnValue: Data! { get { if Thread.isMainThread { - return acceptInvitationUnderlyingReturnValue + return loadMediaContentForSourceUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: Data? = nil DispatchQueue.main.sync { - returnValue = acceptInvitationUnderlyingReturnValue + returnValue = loadMediaContentForSourceUnderlyingReturnValue } return returnValue! @@ -8942,35 +9293,43 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - acceptInvitationUnderlyingReturnValue = newValue + loadMediaContentForSourceUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - acceptInvitationUnderlyingReturnValue = newValue + loadMediaContentForSourceUnderlyingReturnValue = newValue } } } } - var acceptInvitationClosure: (() async -> Result)? + var loadMediaContentForSourceClosure: ((MediaSourceProxy) async throws -> Data)? - func acceptInvitation() async -> Result { - acceptInvitationCallsCount += 1 - if let acceptInvitationClosure = acceptInvitationClosure { - return await acceptInvitationClosure() + func loadMediaContentForSource(_ source: MediaSourceProxy) async throws -> Data { + if let error = loadMediaContentForSourceThrowableError { + throw error + } + loadMediaContentForSourceCallsCount += 1 + loadMediaContentForSourceReceivedSource = source + DispatchQueue.main.async { + self.loadMediaContentForSourceReceivedInvocations.append(source) + } + if let loadMediaContentForSourceClosure = loadMediaContentForSourceClosure { + return try await loadMediaContentForSourceClosure(source) } else { - return acceptInvitationReturnValue + return loadMediaContentForSourceReturnValue } } - //MARK: - invite + //MARK: - loadMediaThumbnailForSource - var inviteUserIDUnderlyingCallsCount = 0 - var inviteUserIDCallsCount: Int { + var loadMediaThumbnailForSourceWidthHeightThrowableError: Error? + var loadMediaThumbnailForSourceWidthHeightUnderlyingCallsCount = 0 + var loadMediaThumbnailForSourceWidthHeightCallsCount: Int { get { if Thread.isMainThread { - return inviteUserIDUnderlyingCallsCount + return loadMediaThumbnailForSourceWidthHeightUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = inviteUserIDUnderlyingCallsCount + returnValue = loadMediaThumbnailForSourceWidthHeightUnderlyingCallsCount } return returnValue! @@ -8978,29 +9337,29 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - inviteUserIDUnderlyingCallsCount = newValue + loadMediaThumbnailForSourceWidthHeightUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - inviteUserIDUnderlyingCallsCount = newValue + loadMediaThumbnailForSourceWidthHeightUnderlyingCallsCount = newValue } } } } - var inviteUserIDCalled: Bool { - return inviteUserIDCallsCount > 0 + var loadMediaThumbnailForSourceWidthHeightCalled: Bool { + return loadMediaThumbnailForSourceWidthHeightCallsCount > 0 } - var inviteUserIDReceivedUserID: String? - var inviteUserIDReceivedInvocations: [String] = [] + var loadMediaThumbnailForSourceWidthHeightReceivedArguments: (source: MediaSourceProxy, width: UInt, height: UInt)? + var loadMediaThumbnailForSourceWidthHeightReceivedInvocations: [(source: MediaSourceProxy, width: UInt, height: UInt)] = [] - var inviteUserIDUnderlyingReturnValue: Result! - var inviteUserIDReturnValue: Result! { + var loadMediaThumbnailForSourceWidthHeightUnderlyingReturnValue: Data! + var loadMediaThumbnailForSourceWidthHeightReturnValue: Data! { get { if Thread.isMainThread { - return inviteUserIDUnderlyingReturnValue + return loadMediaThumbnailForSourceWidthHeightUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: Data? = nil DispatchQueue.main.sync { - returnValue = inviteUserIDUnderlyingReturnValue + returnValue = loadMediaThumbnailForSourceWidthHeightUnderlyingReturnValue } return returnValue! @@ -9008,39 +9367,43 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - inviteUserIDUnderlyingReturnValue = newValue + loadMediaThumbnailForSourceWidthHeightUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - inviteUserIDUnderlyingReturnValue = newValue + loadMediaThumbnailForSourceWidthHeightUnderlyingReturnValue = newValue } } } } - var inviteUserIDClosure: ((String) async -> Result)? + var loadMediaThumbnailForSourceWidthHeightClosure: ((MediaSourceProxy, UInt, UInt) async throws -> Data)? - func invite(userID: String) async -> Result { - inviteUserIDCallsCount += 1 - inviteUserIDReceivedUserID = userID + func loadMediaThumbnailForSource(_ source: MediaSourceProxy, width: UInt, height: UInt) async throws -> Data { + if let error = loadMediaThumbnailForSourceWidthHeightThrowableError { + throw error + } + loadMediaThumbnailForSourceWidthHeightCallsCount += 1 + loadMediaThumbnailForSourceWidthHeightReceivedArguments = (source: source, width: width, height: height) DispatchQueue.main.async { - self.inviteUserIDReceivedInvocations.append(userID) + self.loadMediaThumbnailForSourceWidthHeightReceivedInvocations.append((source: source, width: width, height: height)) } - if let inviteUserIDClosure = inviteUserIDClosure { - return await inviteUserIDClosure(userID) + if let loadMediaThumbnailForSourceWidthHeightClosure = loadMediaThumbnailForSourceWidthHeightClosure { + return try await loadMediaThumbnailForSourceWidthHeightClosure(source, width, height) } else { - return inviteUserIDReturnValue + return loadMediaThumbnailForSourceWidthHeightReturnValue } } - //MARK: - setName + //MARK: - loadMediaFileForSource - var setNameUnderlyingCallsCount = 0 - var setNameCallsCount: Int { + var loadMediaFileForSourceBodyThrowableError: Error? + var loadMediaFileForSourceBodyUnderlyingCallsCount = 0 + var loadMediaFileForSourceBodyCallsCount: Int { get { if Thread.isMainThread { - return setNameUnderlyingCallsCount + return loadMediaFileForSourceBodyUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = setNameUnderlyingCallsCount + returnValue = loadMediaFileForSourceBodyUnderlyingCallsCount } return returnValue! @@ -9048,29 +9411,29 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - setNameUnderlyingCallsCount = newValue + loadMediaFileForSourceBodyUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - setNameUnderlyingCallsCount = newValue + loadMediaFileForSourceBodyUnderlyingCallsCount = newValue } } } } - var setNameCalled: Bool { - return setNameCallsCount > 0 + var loadMediaFileForSourceBodyCalled: Bool { + return loadMediaFileForSourceBodyCallsCount > 0 } - var setNameReceivedName: String? - var setNameReceivedInvocations: [String] = [] + var loadMediaFileForSourceBodyReceivedArguments: (source: MediaSourceProxy, body: String?)? + var loadMediaFileForSourceBodyReceivedInvocations: [(source: MediaSourceProxy, body: String?)] = [] - var setNameUnderlyingReturnValue: Result! - var setNameReturnValue: Result! { + var loadMediaFileForSourceBodyUnderlyingReturnValue: MediaFileHandleProxy! + var loadMediaFileForSourceBodyReturnValue: MediaFileHandleProxy! { get { if Thread.isMainThread { - return setNameUnderlyingReturnValue + return loadMediaFileForSourceBodyUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: MediaFileHandleProxy? = nil DispatchQueue.main.sync { - returnValue = setNameUnderlyingReturnValue + returnValue = loadMediaFileForSourceBodyUnderlyingReturnValue } return returnValue! @@ -9078,69 +9441,62 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - setNameUnderlyingReturnValue = newValue + loadMediaFileForSourceBodyUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - setNameUnderlyingReturnValue = newValue + loadMediaFileForSourceBodyUnderlyingReturnValue = newValue } } } } - var setNameClosure: ((String) async -> Result)? + var loadMediaFileForSourceBodyClosure: ((MediaSourceProxy, String?) async throws -> MediaFileHandleProxy)? - func setName(_ name: String) async -> Result { - setNameCallsCount += 1 - setNameReceivedName = name + func loadMediaFileForSource(_ source: MediaSourceProxy, body: String?) async throws -> MediaFileHandleProxy { + if let error = loadMediaFileForSourceBodyThrowableError { + throw error + } + loadMediaFileForSourceBodyCallsCount += 1 + loadMediaFileForSourceBodyReceivedArguments = (source: source, body: body) DispatchQueue.main.async { - self.setNameReceivedInvocations.append(name) + self.loadMediaFileForSourceBodyReceivedInvocations.append((source: source, body: body)) } - if let setNameClosure = setNameClosure { - return await setNameClosure(name) + if let loadMediaFileForSourceBodyClosure = loadMediaFileForSourceBodyClosure { + return try await loadMediaFileForSourceBodyClosure(source, body) } else { - return setNameReturnValue + return loadMediaFileForSourceBodyReturnValue } } - //MARK: - setTopic - - var setTopicUnderlyingCallsCount = 0 - var setTopicCallsCount: Int { - get { - if Thread.isMainThread { - return setTopicUnderlyingCallsCount - } else { - var returnValue: Int? = nil - DispatchQueue.main.sync { - returnValue = setTopicUnderlyingCallsCount - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - setTopicUnderlyingCallsCount = newValue - } else { - DispatchQueue.main.sync { - setTopicUnderlyingCallsCount = newValue - } - } - } +} +class MediaPlayerMock: MediaPlayerProtocol { + var mediaSource: MediaSourceProxy? + var duration: TimeInterval { + get { return underlyingDuration } + set(value) { underlyingDuration = value } } - var setTopicCalled: Bool { - return setTopicCallsCount > 0 + var underlyingDuration: TimeInterval! + var currentTime: TimeInterval { + get { return underlyingCurrentTime } + set(value) { underlyingCurrentTime = value } } - var setTopicReceivedTopic: String? - var setTopicReceivedInvocations: [String] = [] + var underlyingCurrentTime: TimeInterval! + var url: URL? + var state: MediaPlayerState { + get { return underlyingState } + set(value) { underlyingState = value } + } + var underlyingState: MediaPlayerState! - var setTopicUnderlyingReturnValue: Result! - var setTopicReturnValue: Result! { + //MARK: - load + + var loadMediaSourceUsingAutoplayUnderlyingCallsCount = 0 + var loadMediaSourceUsingAutoplayCallsCount: Int { get { if Thread.isMainThread { - return setTopicUnderlyingReturnValue + return loadMediaSourceUsingAutoplayUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = setTopicUnderlyingReturnValue + returnValue = loadMediaSourceUsingAutoplayUnderlyingCallsCount } return returnValue! @@ -9148,39 +9504,40 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - setTopicUnderlyingReturnValue = newValue + loadMediaSourceUsingAutoplayUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - setTopicUnderlyingReturnValue = newValue + loadMediaSourceUsingAutoplayUnderlyingCallsCount = newValue } } } } - var setTopicClosure: ((String) async -> Result)? + 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 setTopic(_ topic: String) async -> Result { - setTopicCallsCount += 1 - setTopicReceivedTopic = topic + func load(mediaSource: MediaSourceProxy, using url: URL, autoplay: Bool) { + loadMediaSourceUsingAutoplayCallsCount += 1 + loadMediaSourceUsingAutoplayReceivedArguments = (mediaSource: mediaSource, url: url, autoplay: autoplay) DispatchQueue.main.async { - self.setTopicReceivedInvocations.append(topic) - } - if let setTopicClosure = setTopicClosure { - return await setTopicClosure(topic) - } else { - return setTopicReturnValue + self.loadMediaSourceUsingAutoplayReceivedInvocations.append((mediaSource: mediaSource, url: url, autoplay: autoplay)) } + loadMediaSourceUsingAutoplayClosure?(mediaSource, url, autoplay) } - //MARK: - removeAvatar + //MARK: - reset - var removeAvatarUnderlyingCallsCount = 0 - var removeAvatarCallsCount: Int { + var resetUnderlyingCallsCount = 0 + var resetCallsCount: Int { get { if Thread.isMainThread { - return removeAvatarUnderlyingCallsCount + return resetUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = removeAvatarUnderlyingCallsCount + returnValue = resetUnderlyingCallsCount } return returnValue! @@ -9188,27 +9545,34 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - removeAvatarUnderlyingCallsCount = newValue + resetUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - removeAvatarUnderlyingCallsCount = newValue + resetUnderlyingCallsCount = newValue } } } } - var removeAvatarCalled: Bool { - return removeAvatarCallsCount > 0 + var resetCalled: Bool { + return resetCallsCount > 0 } + var resetClosure: (() -> Void)? - var removeAvatarUnderlyingReturnValue: Result! - var removeAvatarReturnValue: Result! { + func reset() { + resetCallsCount += 1 + resetClosure?() + } + //MARK: - play + + var playUnderlyingCallsCount = 0 + var playCallsCount: Int { get { if Thread.isMainThread { - return removeAvatarUnderlyingReturnValue + return playUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = removeAvatarUnderlyingReturnValue + returnValue = playUnderlyingCallsCount } return returnValue! @@ -9216,35 +9580,34 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - removeAvatarUnderlyingReturnValue = newValue + playUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - removeAvatarUnderlyingReturnValue = newValue + playUnderlyingCallsCount = newValue } } } } - var removeAvatarClosure: (() async -> Result)? + var playCalled: Bool { + return playCallsCount > 0 + } + var playClosure: (() -> Void)? - func removeAvatar() async -> Result { - removeAvatarCallsCount += 1 - if let removeAvatarClosure = removeAvatarClosure { - return await removeAvatarClosure() - } else { - return removeAvatarReturnValue - } + func play() { + playCallsCount += 1 + playClosure?() } - //MARK: - uploadAvatar + //MARK: - pause - var uploadAvatarMediaUnderlyingCallsCount = 0 - var uploadAvatarMediaCallsCount: Int { + var pauseUnderlyingCallsCount = 0 + var pauseCallsCount: Int { get { if Thread.isMainThread { - return uploadAvatarMediaUnderlyingCallsCount + return pauseUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = uploadAvatarMediaUnderlyingCallsCount + returnValue = pauseUnderlyingCallsCount } return returnValue! @@ -9252,29 +9615,34 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - uploadAvatarMediaUnderlyingCallsCount = newValue + pauseUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - uploadAvatarMediaUnderlyingCallsCount = newValue + pauseUnderlyingCallsCount = newValue } } } } - var uploadAvatarMediaCalled: Bool { - return uploadAvatarMediaCallsCount > 0 + var pauseCalled: Bool { + return pauseCallsCount > 0 } - var uploadAvatarMediaReceivedMedia: MediaInfo? - var uploadAvatarMediaReceivedInvocations: [MediaInfo] = [] + var pauseClosure: (() -> Void)? - var uploadAvatarMediaUnderlyingReturnValue: Result! - var uploadAvatarMediaReturnValue: Result! { + func pause() { + pauseCallsCount += 1 + pauseClosure?() + } + //MARK: - stop + + var stopUnderlyingCallsCount = 0 + var stopCallsCount: Int { get { if Thread.isMainThread { - return uploadAvatarMediaUnderlyingReturnValue + return stopUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = uploadAvatarMediaUnderlyingReturnValue + returnValue = stopUnderlyingCallsCount } return returnValue! @@ -9282,39 +9650,34 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - uploadAvatarMediaUnderlyingReturnValue = newValue + stopUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - uploadAvatarMediaUnderlyingReturnValue = newValue + stopUnderlyingCallsCount = newValue } } } } - var uploadAvatarMediaClosure: ((MediaInfo) async -> Result)? + var stopCalled: Bool { + return stopCallsCount > 0 + } + var stopClosure: (() -> Void)? - func uploadAvatar(media: MediaInfo) async -> Result { - uploadAvatarMediaCallsCount += 1 - uploadAvatarMediaReceivedMedia = media - DispatchQueue.main.async { - self.uploadAvatarMediaReceivedInvocations.append(media) - } - if let uploadAvatarMediaClosure = uploadAvatarMediaClosure { - return await uploadAvatarMediaClosure(media) - } else { - return uploadAvatarMediaReturnValue - } + func stop() { + stopCallsCount += 1 + stopClosure?() } - //MARK: - markAsRead + //MARK: - seek - var markAsReadReceiptTypeUnderlyingCallsCount = 0 - var markAsReadReceiptTypeCallsCount: Int { + var seekToUnderlyingCallsCount = 0 + var seekToCallsCount: Int { get { if Thread.isMainThread { - return markAsReadReceiptTypeUnderlyingCallsCount + return seekToUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = markAsReadReceiptTypeUnderlyingCallsCount + returnValue = seekToUnderlyingCallsCount } return returnValue! @@ -9322,29 +9685,43 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - markAsReadReceiptTypeUnderlyingCallsCount = newValue + seekToUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - markAsReadReceiptTypeUnderlyingCallsCount = newValue + seekToUnderlyingCallsCount = newValue } } } } - var markAsReadReceiptTypeCalled: Bool { - return markAsReadReceiptTypeCallsCount > 0 + var seekToCalled: Bool { + return seekToCallsCount > 0 } - var markAsReadReceiptTypeReceivedReceiptType: ReceiptType? - var markAsReadReceiptTypeReceivedInvocations: [ReceiptType] = [] + var seekToReceivedProgress: Double? + var seekToReceivedInvocations: [Double] = [] + var seekToClosure: ((Double) async -> Void)? - var markAsReadReceiptTypeUnderlyingReturnValue: Result! - var markAsReadReceiptTypeReturnValue: Result! { + 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 markAsReadReceiptTypeUnderlyingReturnValue + return playerForUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = markAsReadReceiptTypeUnderlyingReturnValue + returnValue = playerForUnderlyingCallsCount } return returnValue! @@ -9352,39 +9729,29 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - markAsReadReceiptTypeUnderlyingReturnValue = newValue + playerForUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - markAsReadReceiptTypeUnderlyingReturnValue = newValue + playerForUnderlyingCallsCount = newValue } } } } - var markAsReadReceiptTypeClosure: ((ReceiptType) async -> Result)? - - func markAsRead(receiptType: ReceiptType) async -> Result { - markAsReadReceiptTypeCallsCount += 1 - markAsReadReceiptTypeReceivedReceiptType = receiptType - DispatchQueue.main.async { - self.markAsReadReceiptTypeReceivedInvocations.append(receiptType) - } - if let markAsReadReceiptTypeClosure = markAsReadReceiptTypeClosure { - return await markAsReadReceiptTypeClosure(receiptType) - } else { - return markAsReadReceiptTypeReturnValue - } + var playerForCalled: Bool { + return playerForCallsCount > 0 } - //MARK: - edit + var playerForReceivedMediaSource: MediaSourceProxy? + var playerForReceivedInvocations: [MediaSourceProxy] = [] - var editEventIDNewContentUnderlyingCallsCount = 0 - var editEventIDNewContentCallsCount: Int { + var playerForUnderlyingReturnValue: Result! + var playerForReturnValue: Result! { get { if Thread.isMainThread { - return editEventIDNewContentUnderlyingCallsCount + return playerForUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = editEventIDNewContentUnderlyingCallsCount + returnValue = playerForUnderlyingReturnValue } return returnValue! @@ -9392,29 +9759,39 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - editEventIDNewContentUnderlyingCallsCount = newValue + playerForUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - editEventIDNewContentUnderlyingCallsCount = newValue + playerForUnderlyingReturnValue = newValue } } } } - var editEventIDNewContentCalled: Bool { - return editEventIDNewContentCallsCount > 0 + var playerForClosure: ((MediaSourceProxy) -> Result)? + + 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 + } } - var editEventIDNewContentReceivedArguments: (eventID: String, newContent: RoomMessageEventContentWithoutRelation)? - var editEventIDNewContentReceivedInvocations: [(eventID: String, newContent: RoomMessageEventContentWithoutRelation)] = [] + //MARK: - playerState - var editEventIDNewContentUnderlyingReturnValue: Result! - var editEventIDNewContentReturnValue: Result! { + var playerStateForUnderlyingCallsCount = 0 + var playerStateForCallsCount: Int { get { if Thread.isMainThread { - return editEventIDNewContentUnderlyingReturnValue + return playerStateForUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = editEventIDNewContentUnderlyingReturnValue + returnValue = playerStateForUnderlyingCallsCount } return returnValue! @@ -9422,39 +9799,29 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - editEventIDNewContentUnderlyingReturnValue = newValue + playerStateForUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - editEventIDNewContentUnderlyingReturnValue = newValue + playerStateForUnderlyingCallsCount = newValue } } } } - var editEventIDNewContentClosure: ((String, RoomMessageEventContentWithoutRelation) async -> Result)? - - func edit(eventID: String, newContent: RoomMessageEventContentWithoutRelation) async -> Result { - editEventIDNewContentCallsCount += 1 - editEventIDNewContentReceivedArguments = (eventID: eventID, newContent: newContent) - DispatchQueue.main.async { - self.editEventIDNewContentReceivedInvocations.append((eventID: eventID, newContent: newContent)) - } - if let editEventIDNewContentClosure = editEventIDNewContentClosure { - return await editEventIDNewContentClosure(eventID, newContent) - } else { - return editEventIDNewContentReturnValue - } + var playerStateForCalled: Bool { + return playerStateForCallsCount > 0 } - //MARK: - sendTypingNotification + var playerStateForReceivedId: AudioPlayerStateIdentifier? + var playerStateForReceivedInvocations: [AudioPlayerStateIdentifier] = [] - var sendTypingNotificationIsTypingUnderlyingCallsCount = 0 - var sendTypingNotificationIsTypingCallsCount: Int { + var playerStateForUnderlyingReturnValue: AudioPlayerState? + var playerStateForReturnValue: AudioPlayerState? { get { if Thread.isMainThread { - return sendTypingNotificationIsTypingUnderlyingCallsCount + return playerStateForUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: AudioPlayerState?? = nil DispatchQueue.main.sync { - returnValue = sendTypingNotificationIsTypingUnderlyingCallsCount + returnValue = playerStateForUnderlyingReturnValue } return returnValue! @@ -9462,29 +9829,39 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - sendTypingNotificationIsTypingUnderlyingCallsCount = newValue + playerStateForUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - sendTypingNotificationIsTypingUnderlyingCallsCount = newValue + playerStateForUnderlyingReturnValue = newValue } } } } - var sendTypingNotificationIsTypingCalled: Bool { - return sendTypingNotificationIsTypingCallsCount > 0 + var playerStateForClosure: ((AudioPlayerStateIdentifier) -> AudioPlayerState?)? + + func playerState(for id: AudioPlayerStateIdentifier) -> AudioPlayerState? { + playerStateForCallsCount += 1 + playerStateForReceivedId = id + DispatchQueue.main.async { + self.playerStateForReceivedInvocations.append(id) + } + if let playerStateForClosure = playerStateForClosure { + return playerStateForClosure(id) + } else { + return playerStateForReturnValue + } } - var sendTypingNotificationIsTypingReceivedIsTyping: Bool? - var sendTypingNotificationIsTypingReceivedInvocations: [Bool] = [] + //MARK: - register - var sendTypingNotificationIsTypingUnderlyingReturnValue: Result! - var sendTypingNotificationIsTypingReturnValue: Result! { + var registerAudioPlayerStateUnderlyingCallsCount = 0 + var registerAudioPlayerStateCallsCount: Int { get { if Thread.isMainThread { - return sendTypingNotificationIsTypingUnderlyingReturnValue + return registerAudioPlayerStateUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = sendTypingNotificationIsTypingUnderlyingReturnValue + returnValue = registerAudioPlayerStateUnderlyingCallsCount } return returnValue! @@ -9492,40 +9869,40 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - sendTypingNotificationIsTypingUnderlyingReturnValue = newValue + registerAudioPlayerStateUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - sendTypingNotificationIsTypingUnderlyingReturnValue = newValue + registerAudioPlayerStateUnderlyingCallsCount = newValue } } } } - var sendTypingNotificationIsTypingClosure: ((Bool) async -> Result)? + var registerAudioPlayerStateCalled: Bool { + return registerAudioPlayerStateCallsCount > 0 + } + var registerAudioPlayerStateReceivedAudioPlayerState: AudioPlayerState? + var registerAudioPlayerStateReceivedInvocations: [AudioPlayerState] = [] + var registerAudioPlayerStateClosure: ((AudioPlayerState) -> Void)? - @discardableResult - func sendTypingNotification(isTyping: Bool) async -> Result { - sendTypingNotificationIsTypingCallsCount += 1 - sendTypingNotificationIsTypingReceivedIsTyping = isTyping + func register(audioPlayerState: AudioPlayerState) { + registerAudioPlayerStateCallsCount += 1 + registerAudioPlayerStateReceivedAudioPlayerState = audioPlayerState DispatchQueue.main.async { - self.sendTypingNotificationIsTypingReceivedInvocations.append(isTyping) - } - if let sendTypingNotificationIsTypingClosure = sendTypingNotificationIsTypingClosure { - return await sendTypingNotificationIsTypingClosure(isTyping) - } else { - return sendTypingNotificationIsTypingReturnValue + self.registerAudioPlayerStateReceivedInvocations.append(audioPlayerState) } + registerAudioPlayerStateClosure?(audioPlayerState) } - //MARK: - flagAsUnread + //MARK: - unregister - var flagAsUnreadUnderlyingCallsCount = 0 - var flagAsUnreadCallsCount: Int { + var unregisterAudioPlayerStateUnderlyingCallsCount = 0 + var unregisterAudioPlayerStateCallsCount: Int { get { if Thread.isMainThread { - return flagAsUnreadUnderlyingCallsCount + return unregisterAudioPlayerStateUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = flagAsUnreadUnderlyingCallsCount + returnValue = unregisterAudioPlayerStateUnderlyingCallsCount } return returnValue! @@ -9533,29 +9910,40 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - flagAsUnreadUnderlyingCallsCount = newValue + unregisterAudioPlayerStateUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - flagAsUnreadUnderlyingCallsCount = newValue + unregisterAudioPlayerStateUnderlyingCallsCount = newValue } } } } - var flagAsUnreadCalled: Bool { - return flagAsUnreadCallsCount > 0 + var unregisterAudioPlayerStateCalled: Bool { + return unregisterAudioPlayerStateCallsCount > 0 } - var flagAsUnreadReceivedIsUnread: Bool? - var flagAsUnreadReceivedInvocations: [Bool] = [] + var unregisterAudioPlayerStateReceivedAudioPlayerState: AudioPlayerState? + var unregisterAudioPlayerStateReceivedInvocations: [AudioPlayerState] = [] + var unregisterAudioPlayerStateClosure: ((AudioPlayerState) -> Void)? - var flagAsUnreadUnderlyingReturnValue: Result! - var flagAsUnreadReturnValue: Result! { + func unregister(audioPlayerState: AudioPlayerState) { + unregisterAudioPlayerStateCallsCount += 1 + unregisterAudioPlayerStateReceivedAudioPlayerState = audioPlayerState + DispatchQueue.main.async { + self.unregisterAudioPlayerStateReceivedInvocations.append(audioPlayerState) + } + unregisterAudioPlayerStateClosure?(audioPlayerState) + } + //MARK: - detachAllStates + + var detachAllStatesExceptUnderlyingCallsCount = 0 + var detachAllStatesExceptCallsCount: Int { get { if Thread.isMainThread { - return flagAsUnreadUnderlyingReturnValue + return detachAllStatesExceptUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = flagAsUnreadUnderlyingReturnValue + returnValue = detachAllStatesExceptUnderlyingCallsCount } return returnValue! @@ -9563,39 +9951,52 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - flagAsUnreadUnderlyingReturnValue = newValue + detachAllStatesExceptUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - flagAsUnreadUnderlyingReturnValue = newValue + detachAllStatesExceptUnderlyingCallsCount = newValue } } } } - var flagAsUnreadClosure: ((Bool) async -> Result)? + var detachAllStatesExceptCalled: Bool { + return detachAllStatesExceptCallsCount > 0 + } + var detachAllStatesExceptReceivedException: AudioPlayerState? + var detachAllStatesExceptReceivedInvocations: [AudioPlayerState?] = [] + var detachAllStatesExceptClosure: ((AudioPlayerState?) async -> Void)? - func flagAsUnread(_ isUnread: Bool) async -> Result { - flagAsUnreadCallsCount += 1 - flagAsUnreadReceivedIsUnread = isUnread + func detachAllStates(except exception: AudioPlayerState?) async { + detachAllStatesExceptCallsCount += 1 + detachAllStatesExceptReceivedException = exception DispatchQueue.main.async { - self.flagAsUnreadReceivedInvocations.append(isUnread) - } - if let flagAsUnreadClosure = flagAsUnreadClosure { - return await flagAsUnreadClosure(isUnread) - } else { - return flagAsUnreadReturnValue + self.detachAllStatesExceptReceivedInvocations.append(exception) } + await detachAllStatesExceptClosure?(exception) } - //MARK: - flagAsFavourite +} +class NetworkMonitorMock: NetworkMonitorProtocol { + var reachabilityPublisher: CurrentValuePublisher { + get { return underlyingReachabilityPublisher } + set(value) { underlyingReachabilityPublisher = value } + } + var underlyingReachabilityPublisher: CurrentValuePublisher! - var flagAsFavouriteUnderlyingCallsCount = 0 - var flagAsFavouriteCallsCount: Int { +} +class NotificationManagerMock: NotificationManagerProtocol { + weak var delegate: NotificationManagerDelegate? + + //MARK: - start + + var startUnderlyingCallsCount = 0 + var startCallsCount: Int { get { if Thread.isMainThread { - return flagAsFavouriteUnderlyingCallsCount + return startUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = flagAsFavouriteUnderlyingCallsCount + returnValue = startUnderlyingCallsCount } return returnValue! @@ -9603,29 +10004,34 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - flagAsFavouriteUnderlyingCallsCount = newValue + startUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - flagAsFavouriteUnderlyingCallsCount = newValue + startUnderlyingCallsCount = newValue } } } } - var flagAsFavouriteCalled: Bool { - return flagAsFavouriteCallsCount > 0 + var startCalled: Bool { + return startCallsCount > 0 } - var flagAsFavouriteReceivedIsFavourite: Bool? - var flagAsFavouriteReceivedInvocations: [Bool] = [] + var startClosure: (() -> Void)? - var flagAsFavouriteUnderlyingReturnValue: Result! - var flagAsFavouriteReturnValue: Result! { + func start() { + startCallsCount += 1 + startClosure?() + } + //MARK: - register + + var registerWithUnderlyingCallsCount = 0 + var registerWithCallsCount: Int { get { if Thread.isMainThread { - return flagAsFavouriteUnderlyingReturnValue + return registerWithUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = flagAsFavouriteUnderlyingReturnValue + returnValue = registerWithUnderlyingCallsCount } return returnValue! @@ -9633,39 +10039,29 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - flagAsFavouriteUnderlyingReturnValue = newValue + registerWithUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - flagAsFavouriteUnderlyingReturnValue = newValue + registerWithUnderlyingCallsCount = newValue } } } } - var flagAsFavouriteClosure: ((Bool) async -> Result)? - - func flagAsFavourite(_ isFavourite: Bool) async -> Result { - flagAsFavouriteCallsCount += 1 - flagAsFavouriteReceivedIsFavourite = isFavourite - DispatchQueue.main.async { - self.flagAsFavouriteReceivedInvocations.append(isFavourite) - } - if let flagAsFavouriteClosure = flagAsFavouriteClosure { - return await flagAsFavouriteClosure(isFavourite) - } else { - return flagAsFavouriteReturnValue - } + var registerWithCalled: Bool { + return registerWithCallsCount > 0 } - //MARK: - powerLevels + var registerWithReceivedDeviceToken: Data? + var registerWithReceivedInvocations: [Data] = [] - var powerLevelsUnderlyingCallsCount = 0 - var powerLevelsCallsCount: Int { + var registerWithUnderlyingReturnValue: Bool! + var registerWithReturnValue: Bool! { get { if Thread.isMainThread { - return powerLevelsUnderlyingCallsCount + return registerWithUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Bool? = nil DispatchQueue.main.sync { - returnValue = powerLevelsUnderlyingCallsCount + returnValue = registerWithUnderlyingReturnValue } return returnValue! @@ -9673,27 +10069,39 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - powerLevelsUnderlyingCallsCount = newValue + registerWithUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - powerLevelsUnderlyingCallsCount = newValue + registerWithUnderlyingReturnValue = newValue } } } } - var powerLevelsCalled: Bool { - return powerLevelsCallsCount > 0 + var registerWithClosure: ((Data) async -> Bool)? + + func register(with deviceToken: Data) async -> Bool { + registerWithCallsCount += 1 + registerWithReceivedDeviceToken = deviceToken + DispatchQueue.main.async { + self.registerWithReceivedInvocations.append(deviceToken) + } + if let registerWithClosure = registerWithClosure { + return await registerWithClosure(deviceToken) + } else { + return registerWithReturnValue + } } + //MARK: - registrationFailed - var powerLevelsUnderlyingReturnValue: Result! - var powerLevelsReturnValue: Result! { + var registrationFailedWithUnderlyingCallsCount = 0 + var registrationFailedWithCallsCount: Int { get { if Thread.isMainThread { - return powerLevelsUnderlyingReturnValue + return registrationFailedWithUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = powerLevelsUnderlyingReturnValue + returnValue = registrationFailedWithUnderlyingCallsCount } return returnValue! @@ -9701,35 +10109,40 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - powerLevelsUnderlyingReturnValue = newValue + registrationFailedWithUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - powerLevelsUnderlyingReturnValue = newValue + registrationFailedWithUnderlyingCallsCount = newValue } } } } - var powerLevelsClosure: (() async -> Result)? - - func powerLevels() async -> Result { - powerLevelsCallsCount += 1 - if let powerLevelsClosure = powerLevelsClosure { - return await powerLevelsClosure() - } else { - return powerLevelsReturnValue + var registrationFailedWithCalled: Bool { + return registrationFailedWithCallsCount > 0 + } + var registrationFailedWithReceivedError: Error? + var registrationFailedWithReceivedInvocations: [Error] = [] + var registrationFailedWithClosure: ((Error) -> Void)? + + func registrationFailed(with error: Error) { + registrationFailedWithCallsCount += 1 + registrationFailedWithReceivedError = error + DispatchQueue.main.async { + self.registrationFailedWithReceivedInvocations.append(error) } + registrationFailedWithClosure?(error) } - //MARK: - applyPowerLevelChanges + //MARK: - showLocalNotification - var applyPowerLevelChangesUnderlyingCallsCount = 0 - var applyPowerLevelChangesCallsCount: Int { + var showLocalNotificationWithSubtitleUnderlyingCallsCount = 0 + var showLocalNotificationWithSubtitleCallsCount: Int { get { if Thread.isMainThread { - return applyPowerLevelChangesUnderlyingCallsCount + return showLocalNotificationWithSubtitleUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = applyPowerLevelChangesUnderlyingCallsCount + returnValue = showLocalNotificationWithSubtitleUnderlyingCallsCount } return returnValue! @@ -9737,29 +10150,40 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - applyPowerLevelChangesUnderlyingCallsCount = newValue + showLocalNotificationWithSubtitleUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - applyPowerLevelChangesUnderlyingCallsCount = newValue + showLocalNotificationWithSubtitleUnderlyingCallsCount = newValue } } } } - var applyPowerLevelChangesCalled: Bool { - return applyPowerLevelChangesCallsCount > 0 + var showLocalNotificationWithSubtitleCalled: Bool { + return showLocalNotificationWithSubtitleCallsCount > 0 } - var applyPowerLevelChangesReceivedChanges: RoomPowerLevelChanges? - var applyPowerLevelChangesReceivedInvocations: [RoomPowerLevelChanges] = [] + var showLocalNotificationWithSubtitleReceivedArguments: (title: String, subtitle: String?)? + var showLocalNotificationWithSubtitleReceivedInvocations: [(title: String, subtitle: String?)] = [] + var showLocalNotificationWithSubtitleClosure: ((String, String?) async -> Void)? - var applyPowerLevelChangesUnderlyingReturnValue: Result! - var applyPowerLevelChangesReturnValue: Result! { + func showLocalNotification(with title: String, subtitle: String?) async { + showLocalNotificationWithSubtitleCallsCount += 1 + showLocalNotificationWithSubtitleReceivedArguments = (title: title, subtitle: subtitle) + DispatchQueue.main.async { + self.showLocalNotificationWithSubtitleReceivedInvocations.append((title: title, subtitle: subtitle)) + } + await showLocalNotificationWithSubtitleClosure?(title, subtitle) + } + //MARK: - setUserSession + + var setUserSessionUnderlyingCallsCount = 0 + var setUserSessionCallsCount: Int { get { if Thread.isMainThread { - return applyPowerLevelChangesUnderlyingReturnValue + return setUserSessionUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = applyPowerLevelChangesUnderlyingReturnValue + returnValue = setUserSessionUnderlyingCallsCount } return returnValue! @@ -9767,39 +10191,40 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - applyPowerLevelChangesUnderlyingReturnValue = newValue + setUserSessionUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - applyPowerLevelChangesUnderlyingReturnValue = newValue + setUserSessionUnderlyingCallsCount = newValue } } } } - var applyPowerLevelChangesClosure: ((RoomPowerLevelChanges) async -> Result)? + var setUserSessionCalled: Bool { + return setUserSessionCallsCount > 0 + } + var setUserSessionReceivedUserSession: UserSessionProtocol? + var setUserSessionReceivedInvocations: [UserSessionProtocol?] = [] + var setUserSessionClosure: ((UserSessionProtocol?) -> Void)? - func applyPowerLevelChanges(_ changes: RoomPowerLevelChanges) async -> Result { - applyPowerLevelChangesCallsCount += 1 - applyPowerLevelChangesReceivedChanges = changes + func setUserSession(_ userSession: UserSessionProtocol?) { + setUserSessionCallsCount += 1 + setUserSessionReceivedUserSession = userSession DispatchQueue.main.async { - self.applyPowerLevelChangesReceivedInvocations.append(changes) - } - if let applyPowerLevelChangesClosure = applyPowerLevelChangesClosure { - return await applyPowerLevelChangesClosure(changes) - } else { - return applyPowerLevelChangesReturnValue + self.setUserSessionReceivedInvocations.append(userSession) } + setUserSessionClosure?(userSession) } - //MARK: - resetPowerLevels + //MARK: - requestAuthorization - var resetPowerLevelsUnderlyingCallsCount = 0 - var resetPowerLevelsCallsCount: Int { + var requestAuthorizationUnderlyingCallsCount = 0 + var requestAuthorizationCallsCount: Int { get { if Thread.isMainThread { - return resetPowerLevelsUnderlyingCallsCount + return requestAuthorizationUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = resetPowerLevelsUnderlyingCallsCount + returnValue = requestAuthorizationUnderlyingCallsCount } return returnValue! @@ -9807,27 +10232,34 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - resetPowerLevelsUnderlyingCallsCount = newValue + requestAuthorizationUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - resetPowerLevelsUnderlyingCallsCount = newValue + requestAuthorizationUnderlyingCallsCount = newValue } } } } - var resetPowerLevelsCalled: Bool { - return resetPowerLevelsCallsCount > 0 + var requestAuthorizationCalled: Bool { + return requestAuthorizationCallsCount > 0 } + var requestAuthorizationClosure: (() -> Void)? - var resetPowerLevelsUnderlyingReturnValue: Result! - var resetPowerLevelsReturnValue: Result! { + func requestAuthorization() { + requestAuthorizationCallsCount += 1 + requestAuthorizationClosure?() + } + //MARK: - removeDeliveredMessageNotifications + + var removeDeliveredMessageNotificationsForUnderlyingCallsCount = 0 + var removeDeliveredMessageNotificationsForCallsCount: Int { get { if Thread.isMainThread { - return resetPowerLevelsUnderlyingReturnValue + return removeDeliveredMessageNotificationsForUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = resetPowerLevelsUnderlyingReturnValue + returnValue = removeDeliveredMessageNotificationsForUnderlyingCallsCount } return returnValue! @@ -9835,35 +10267,40 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - resetPowerLevelsUnderlyingReturnValue = newValue + removeDeliveredMessageNotificationsForUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - resetPowerLevelsUnderlyingReturnValue = newValue + removeDeliveredMessageNotificationsForUnderlyingCallsCount = newValue } } } } - var resetPowerLevelsClosure: (() async -> Result)? + var removeDeliveredMessageNotificationsForCalled: Bool { + return removeDeliveredMessageNotificationsForCallsCount > 0 + } + var removeDeliveredMessageNotificationsForReceivedRoomID: String? + var removeDeliveredMessageNotificationsForReceivedInvocations: [String] = [] + var removeDeliveredMessageNotificationsForClosure: ((String) async -> Void)? - func resetPowerLevels() async -> Result { - resetPowerLevelsCallsCount += 1 - if let resetPowerLevelsClosure = resetPowerLevelsClosure { - return await resetPowerLevelsClosure() - } else { - return resetPowerLevelsReturnValue + func removeDeliveredMessageNotifications(for roomID: String) async { + removeDeliveredMessageNotificationsForCallsCount += 1 + removeDeliveredMessageNotificationsForReceivedRoomID = roomID + DispatchQueue.main.async { + self.removeDeliveredMessageNotificationsForReceivedInvocations.append(roomID) } + await removeDeliveredMessageNotificationsForClosure?(roomID) } - //MARK: - suggestedRole + //MARK: - removeDeliveredInviteNotifications - var suggestedRoleForUnderlyingCallsCount = 0 - var suggestedRoleForCallsCount: Int { + var removeDeliveredInviteNotificationsUnderlyingCallsCount = 0 + var removeDeliveredInviteNotificationsCallsCount: Int { get { if Thread.isMainThread { - return suggestedRoleForUnderlyingCallsCount + return removeDeliveredInviteNotificationsUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = suggestedRoleForUnderlyingCallsCount + returnValue = removeDeliveredInviteNotificationsUnderlyingCallsCount } return returnValue! @@ -9871,29 +10308,43 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - suggestedRoleForUnderlyingCallsCount = newValue + removeDeliveredInviteNotificationsUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - suggestedRoleForUnderlyingCallsCount = newValue + removeDeliveredInviteNotificationsUnderlyingCallsCount = newValue } } } } - var suggestedRoleForCalled: Bool { - return suggestedRoleForCallsCount > 0 + var removeDeliveredInviteNotificationsCalled: Bool { + return removeDeliveredInviteNotificationsCallsCount > 0 } - var suggestedRoleForReceivedUserID: String? - var suggestedRoleForReceivedInvocations: [String] = [] + var removeDeliveredInviteNotificationsClosure: (() async -> Void)? - var suggestedRoleForUnderlyingReturnValue: Result! - var suggestedRoleForReturnValue: Result! { + func removeDeliveredInviteNotifications() async { + removeDeliveredInviteNotificationsCallsCount += 1 + await removeDeliveredInviteNotificationsClosure?() + } +} +class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol { + var callbacks: PassthroughSubject { + get { return underlyingCallbacks } + set(value) { underlyingCallbacks = value } + } + var underlyingCallbacks: PassthroughSubject! + + //MARK: - getNotificationSettings + + var getNotificationSettingsRoomIdIsEncryptedIsOneToOneThrowableError: Error? + var getNotificationSettingsRoomIdIsEncryptedIsOneToOneUnderlyingCallsCount = 0 + var getNotificationSettingsRoomIdIsEncryptedIsOneToOneCallsCount: Int { get { if Thread.isMainThread { - return suggestedRoleForUnderlyingReturnValue + return getNotificationSettingsRoomIdIsEncryptedIsOneToOneUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = suggestedRoleForUnderlyingReturnValue + returnValue = getNotificationSettingsRoomIdIsEncryptedIsOneToOneUnderlyingCallsCount } return returnValue! @@ -9901,39 +10352,29 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - suggestedRoleForUnderlyingReturnValue = newValue + getNotificationSettingsRoomIdIsEncryptedIsOneToOneUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - suggestedRoleForUnderlyingReturnValue = newValue + getNotificationSettingsRoomIdIsEncryptedIsOneToOneUnderlyingCallsCount = newValue } } } } - var suggestedRoleForClosure: ((String) async -> Result)? - - func suggestedRole(for userID: String) async -> Result { - suggestedRoleForCallsCount += 1 - suggestedRoleForReceivedUserID = userID - DispatchQueue.main.async { - self.suggestedRoleForReceivedInvocations.append(userID) - } - if let suggestedRoleForClosure = suggestedRoleForClosure { - return await suggestedRoleForClosure(userID) - } else { - return suggestedRoleForReturnValue - } + var getNotificationSettingsRoomIdIsEncryptedIsOneToOneCalled: Bool { + return getNotificationSettingsRoomIdIsEncryptedIsOneToOneCallsCount > 0 } - //MARK: - updatePowerLevelsForUsers + var getNotificationSettingsRoomIdIsEncryptedIsOneToOneReceivedArguments: (roomId: String, isEncrypted: Bool, isOneToOne: Bool)? + var getNotificationSettingsRoomIdIsEncryptedIsOneToOneReceivedInvocations: [(roomId: String, isEncrypted: Bool, isOneToOne: Bool)] = [] - var updatePowerLevelsForUsersUnderlyingCallsCount = 0 - var updatePowerLevelsForUsersCallsCount: Int { + var getNotificationSettingsRoomIdIsEncryptedIsOneToOneUnderlyingReturnValue: RoomNotificationSettingsProxyProtocol! + var getNotificationSettingsRoomIdIsEncryptedIsOneToOneReturnValue: RoomNotificationSettingsProxyProtocol! { get { if Thread.isMainThread { - return updatePowerLevelsForUsersUnderlyingCallsCount + return getNotificationSettingsRoomIdIsEncryptedIsOneToOneUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: RoomNotificationSettingsProxyProtocol? = nil DispatchQueue.main.sync { - returnValue = updatePowerLevelsForUsersUnderlyingCallsCount + returnValue = getNotificationSettingsRoomIdIsEncryptedIsOneToOneUnderlyingReturnValue } return returnValue! @@ -9941,29 +10382,43 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - updatePowerLevelsForUsersUnderlyingCallsCount = newValue + getNotificationSettingsRoomIdIsEncryptedIsOneToOneUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - updatePowerLevelsForUsersUnderlyingCallsCount = newValue + getNotificationSettingsRoomIdIsEncryptedIsOneToOneUnderlyingReturnValue = newValue } } } } - var updatePowerLevelsForUsersCalled: Bool { - return updatePowerLevelsForUsersCallsCount > 0 + var getNotificationSettingsRoomIdIsEncryptedIsOneToOneClosure: ((String, Bool, Bool) async throws -> RoomNotificationSettingsProxyProtocol)? + + func getNotificationSettings(roomId: String, isEncrypted: Bool, isOneToOne: Bool) async throws -> RoomNotificationSettingsProxyProtocol { + if let error = getNotificationSettingsRoomIdIsEncryptedIsOneToOneThrowableError { + throw error + } + getNotificationSettingsRoomIdIsEncryptedIsOneToOneCallsCount += 1 + getNotificationSettingsRoomIdIsEncryptedIsOneToOneReceivedArguments = (roomId: roomId, isEncrypted: isEncrypted, isOneToOne: isOneToOne) + DispatchQueue.main.async { + self.getNotificationSettingsRoomIdIsEncryptedIsOneToOneReceivedInvocations.append((roomId: roomId, isEncrypted: isEncrypted, isOneToOne: isOneToOne)) + } + if let getNotificationSettingsRoomIdIsEncryptedIsOneToOneClosure = getNotificationSettingsRoomIdIsEncryptedIsOneToOneClosure { + return try await getNotificationSettingsRoomIdIsEncryptedIsOneToOneClosure(roomId, isEncrypted, isOneToOne) + } else { + return getNotificationSettingsRoomIdIsEncryptedIsOneToOneReturnValue + } } - var updatePowerLevelsForUsersReceivedUpdates: [(userID: String, powerLevel: Int64)]? - var updatePowerLevelsForUsersReceivedInvocations: [[(userID: String, powerLevel: Int64)]] = [] + //MARK: - setNotificationMode - var updatePowerLevelsForUsersUnderlyingReturnValue: Result! - var updatePowerLevelsForUsersReturnValue: Result! { + var setNotificationModeRoomIdModeThrowableError: Error? + var setNotificationModeRoomIdModeUnderlyingCallsCount = 0 + var setNotificationModeRoomIdModeCallsCount: Int { get { if Thread.isMainThread { - return updatePowerLevelsForUsersUnderlyingReturnValue + return setNotificationModeRoomIdModeUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = updatePowerLevelsForUsersUnderlyingReturnValue + returnValue = setNotificationModeRoomIdModeUnderlyingCallsCount } return returnValue! @@ -9971,39 +10426,44 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - updatePowerLevelsForUsersUnderlyingReturnValue = newValue + setNotificationModeRoomIdModeUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - updatePowerLevelsForUsersUnderlyingReturnValue = newValue + setNotificationModeRoomIdModeUnderlyingCallsCount = newValue } } } } - var updatePowerLevelsForUsersClosure: (([(userID: String, powerLevel: Int64)]) async -> Result)? + var setNotificationModeRoomIdModeCalled: Bool { + return setNotificationModeRoomIdModeCallsCount > 0 + } + var setNotificationModeRoomIdModeReceivedArguments: (roomId: String, mode: RoomNotificationModeProxy)? + var setNotificationModeRoomIdModeReceivedInvocations: [(roomId: String, mode: RoomNotificationModeProxy)] = [] + var setNotificationModeRoomIdModeClosure: ((String, RoomNotificationModeProxy) async throws -> Void)? - func updatePowerLevelsForUsers(_ updates: [(userID: String, powerLevel: Int64)]) async -> Result { - updatePowerLevelsForUsersCallsCount += 1 - updatePowerLevelsForUsersReceivedUpdates = updates - DispatchQueue.main.async { - self.updatePowerLevelsForUsersReceivedInvocations.append(updates) + func setNotificationMode(roomId: String, mode: RoomNotificationModeProxy) async throws { + if let error = setNotificationModeRoomIdModeThrowableError { + throw error } - if let updatePowerLevelsForUsersClosure = updatePowerLevelsForUsersClosure { - return await updatePowerLevelsForUsersClosure(updates) - } else { - return updatePowerLevelsForUsersReturnValue + setNotificationModeRoomIdModeCallsCount += 1 + setNotificationModeRoomIdModeReceivedArguments = (roomId: roomId, mode: mode) + DispatchQueue.main.async { + self.setNotificationModeRoomIdModeReceivedInvocations.append((roomId: roomId, mode: mode)) } + try await setNotificationModeRoomIdModeClosure?(roomId, mode) } - //MARK: - canUser + //MARK: - getUserDefinedRoomNotificationMode - var canUserUserIDSendStateEventUnderlyingCallsCount = 0 - var canUserUserIDSendStateEventCallsCount: Int { + var getUserDefinedRoomNotificationModeRoomIdThrowableError: Error? + var getUserDefinedRoomNotificationModeRoomIdUnderlyingCallsCount = 0 + var getUserDefinedRoomNotificationModeRoomIdCallsCount: Int { get { if Thread.isMainThread { - return canUserUserIDSendStateEventUnderlyingCallsCount + return getUserDefinedRoomNotificationModeRoomIdUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = canUserUserIDSendStateEventUnderlyingCallsCount + returnValue = getUserDefinedRoomNotificationModeRoomIdUnderlyingCallsCount } return returnValue! @@ -10011,29 +10471,29 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - canUserUserIDSendStateEventUnderlyingCallsCount = newValue + getUserDefinedRoomNotificationModeRoomIdUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - canUserUserIDSendStateEventUnderlyingCallsCount = newValue + getUserDefinedRoomNotificationModeRoomIdUnderlyingCallsCount = newValue } } } } - var canUserUserIDSendStateEventCalled: Bool { - return canUserUserIDSendStateEventCallsCount > 0 + var getUserDefinedRoomNotificationModeRoomIdCalled: Bool { + return getUserDefinedRoomNotificationModeRoomIdCallsCount > 0 } - var canUserUserIDSendStateEventReceivedArguments: (userID: String, event: StateEventType)? - var canUserUserIDSendStateEventReceivedInvocations: [(userID: String, event: StateEventType)] = [] + var getUserDefinedRoomNotificationModeRoomIdReceivedRoomId: String? + var getUserDefinedRoomNotificationModeRoomIdReceivedInvocations: [String] = [] - var canUserUserIDSendStateEventUnderlyingReturnValue: Result! - var canUserUserIDSendStateEventReturnValue: Result! { + var getUserDefinedRoomNotificationModeRoomIdUnderlyingReturnValue: RoomNotificationModeProxy? + var getUserDefinedRoomNotificationModeRoomIdReturnValue: RoomNotificationModeProxy? { get { if Thread.isMainThread { - return canUserUserIDSendStateEventUnderlyingReturnValue + return getUserDefinedRoomNotificationModeRoomIdUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: RoomNotificationModeProxy?? = nil DispatchQueue.main.sync { - returnValue = canUserUserIDSendStateEventUnderlyingReturnValue + returnValue = getUserDefinedRoomNotificationModeRoomIdUnderlyingReturnValue } return returnValue! @@ -10041,39 +10501,42 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - canUserUserIDSendStateEventUnderlyingReturnValue = newValue + getUserDefinedRoomNotificationModeRoomIdUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - canUserUserIDSendStateEventUnderlyingReturnValue = newValue + getUserDefinedRoomNotificationModeRoomIdUnderlyingReturnValue = newValue } } } } - var canUserUserIDSendStateEventClosure: ((String, StateEventType) async -> Result)? + var getUserDefinedRoomNotificationModeRoomIdClosure: ((String) async throws -> RoomNotificationModeProxy?)? - func canUser(userID: String, sendStateEvent event: StateEventType) async -> Result { - canUserUserIDSendStateEventCallsCount += 1 - canUserUserIDSendStateEventReceivedArguments = (userID: userID, event: event) + func getUserDefinedRoomNotificationMode(roomId: String) async throws -> RoomNotificationModeProxy? { + if let error = getUserDefinedRoomNotificationModeRoomIdThrowableError { + throw error + } + getUserDefinedRoomNotificationModeRoomIdCallsCount += 1 + getUserDefinedRoomNotificationModeRoomIdReceivedRoomId = roomId DispatchQueue.main.async { - self.canUserUserIDSendStateEventReceivedInvocations.append((userID: userID, event: event)) + self.getUserDefinedRoomNotificationModeRoomIdReceivedInvocations.append(roomId) } - if let canUserUserIDSendStateEventClosure = canUserUserIDSendStateEventClosure { - return await canUserUserIDSendStateEventClosure(userID, event) + if let getUserDefinedRoomNotificationModeRoomIdClosure = getUserDefinedRoomNotificationModeRoomIdClosure { + return try await getUserDefinedRoomNotificationModeRoomIdClosure(roomId) } else { - return canUserUserIDSendStateEventReturnValue + return getUserDefinedRoomNotificationModeRoomIdReturnValue } } - //MARK: - canUserInvite + //MARK: - getDefaultRoomNotificationMode - var canUserInviteUserIDUnderlyingCallsCount = 0 - var canUserInviteUserIDCallsCount: Int { + var getDefaultRoomNotificationModeIsEncryptedIsOneToOneUnderlyingCallsCount = 0 + var getDefaultRoomNotificationModeIsEncryptedIsOneToOneCallsCount: Int { get { if Thread.isMainThread { - return canUserInviteUserIDUnderlyingCallsCount + return getDefaultRoomNotificationModeIsEncryptedIsOneToOneUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = canUserInviteUserIDUnderlyingCallsCount + returnValue = getDefaultRoomNotificationModeIsEncryptedIsOneToOneUnderlyingCallsCount } return returnValue! @@ -10081,29 +10544,29 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - canUserInviteUserIDUnderlyingCallsCount = newValue + getDefaultRoomNotificationModeIsEncryptedIsOneToOneUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - canUserInviteUserIDUnderlyingCallsCount = newValue + getDefaultRoomNotificationModeIsEncryptedIsOneToOneUnderlyingCallsCount = newValue } } } } - var canUserInviteUserIDCalled: Bool { - return canUserInviteUserIDCallsCount > 0 + var getDefaultRoomNotificationModeIsEncryptedIsOneToOneCalled: Bool { + return getDefaultRoomNotificationModeIsEncryptedIsOneToOneCallsCount > 0 } - var canUserInviteUserIDReceivedUserID: String? - var canUserInviteUserIDReceivedInvocations: [String] = [] + var getDefaultRoomNotificationModeIsEncryptedIsOneToOneReceivedArguments: (isEncrypted: Bool, isOneToOne: Bool)? + var getDefaultRoomNotificationModeIsEncryptedIsOneToOneReceivedInvocations: [(isEncrypted: Bool, isOneToOne: Bool)] = [] - var canUserInviteUserIDUnderlyingReturnValue: Result! - var canUserInviteUserIDReturnValue: Result! { + var getDefaultRoomNotificationModeIsEncryptedIsOneToOneUnderlyingReturnValue: RoomNotificationModeProxy! + var getDefaultRoomNotificationModeIsEncryptedIsOneToOneReturnValue: RoomNotificationModeProxy! { get { if Thread.isMainThread { - return canUserInviteUserIDUnderlyingReturnValue + return getDefaultRoomNotificationModeIsEncryptedIsOneToOneUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: RoomNotificationModeProxy? = nil DispatchQueue.main.sync { - returnValue = canUserInviteUserIDUnderlyingReturnValue + returnValue = getDefaultRoomNotificationModeIsEncryptedIsOneToOneUnderlyingReturnValue } return returnValue! @@ -10111,39 +10574,40 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - canUserInviteUserIDUnderlyingReturnValue = newValue + getDefaultRoomNotificationModeIsEncryptedIsOneToOneUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - canUserInviteUserIDUnderlyingReturnValue = newValue + getDefaultRoomNotificationModeIsEncryptedIsOneToOneUnderlyingReturnValue = newValue } } } } - var canUserInviteUserIDClosure: ((String) async -> Result)? + var getDefaultRoomNotificationModeIsEncryptedIsOneToOneClosure: ((Bool, Bool) async -> RoomNotificationModeProxy)? - func canUserInvite(userID: String) async -> Result { - canUserInviteUserIDCallsCount += 1 - canUserInviteUserIDReceivedUserID = userID + func getDefaultRoomNotificationMode(isEncrypted: Bool, isOneToOne: Bool) async -> RoomNotificationModeProxy { + getDefaultRoomNotificationModeIsEncryptedIsOneToOneCallsCount += 1 + getDefaultRoomNotificationModeIsEncryptedIsOneToOneReceivedArguments = (isEncrypted: isEncrypted, isOneToOne: isOneToOne) DispatchQueue.main.async { - self.canUserInviteUserIDReceivedInvocations.append(userID) + self.getDefaultRoomNotificationModeIsEncryptedIsOneToOneReceivedInvocations.append((isEncrypted: isEncrypted, isOneToOne: isOneToOne)) } - if let canUserInviteUserIDClosure = canUserInviteUserIDClosure { - return await canUserInviteUserIDClosure(userID) + if let getDefaultRoomNotificationModeIsEncryptedIsOneToOneClosure = getDefaultRoomNotificationModeIsEncryptedIsOneToOneClosure { + return await getDefaultRoomNotificationModeIsEncryptedIsOneToOneClosure(isEncrypted, isOneToOne) } else { - return canUserInviteUserIDReturnValue + return getDefaultRoomNotificationModeIsEncryptedIsOneToOneReturnValue } } - //MARK: - canUserRedactOther + //MARK: - setDefaultRoomNotificationMode - var canUserRedactOtherUserIDUnderlyingCallsCount = 0 - var canUserRedactOtherUserIDCallsCount: Int { + var setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeThrowableError: Error? + var setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeUnderlyingCallsCount = 0 + var setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeCallsCount: Int { get { if Thread.isMainThread { - return canUserRedactOtherUserIDUnderlyingCallsCount + return setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = canUserRedactOtherUserIDUnderlyingCallsCount + returnValue = setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeUnderlyingCallsCount } return returnValue! @@ -10151,69 +10615,44 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - canUserRedactOtherUserIDUnderlyingCallsCount = newValue + setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - canUserRedactOtherUserIDUnderlyingCallsCount = newValue + setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeUnderlyingCallsCount = newValue } } } } - var canUserRedactOtherUserIDCalled: Bool { - return canUserRedactOtherUserIDCallsCount > 0 + var setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeCalled: Bool { + return setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeCallsCount > 0 } - var canUserRedactOtherUserIDReceivedUserID: String? - var canUserRedactOtherUserIDReceivedInvocations: [String] = [] - - var canUserRedactOtherUserIDUnderlyingReturnValue: Result! - var canUserRedactOtherUserIDReturnValue: Result! { - get { - if Thread.isMainThread { - return canUserRedactOtherUserIDUnderlyingReturnValue - } else { - var returnValue: Result? = nil - DispatchQueue.main.sync { - returnValue = canUserRedactOtherUserIDUnderlyingReturnValue - } + var setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeReceivedArguments: (isEncrypted: Bool, isOneToOne: Bool, mode: RoomNotificationModeProxy)? + var setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeReceivedInvocations: [(isEncrypted: Bool, isOneToOne: Bool, mode: RoomNotificationModeProxy)] = [] + var setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeClosure: ((Bool, Bool, RoomNotificationModeProxy) async throws -> Void)? - return returnValue! - } - } - set { - if Thread.isMainThread { - canUserRedactOtherUserIDUnderlyingReturnValue = newValue - } else { - DispatchQueue.main.sync { - canUserRedactOtherUserIDUnderlyingReturnValue = newValue - } - } + func setDefaultRoomNotificationMode(isEncrypted: Bool, isOneToOne: Bool, mode: RoomNotificationModeProxy) async throws { + if let error = setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeThrowableError { + throw error } - } - var canUserRedactOtherUserIDClosure: ((String) async -> Result)? - - func canUserRedactOther(userID: String) async -> Result { - canUserRedactOtherUserIDCallsCount += 1 - canUserRedactOtherUserIDReceivedUserID = userID + setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeCallsCount += 1 + setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeReceivedArguments = (isEncrypted: isEncrypted, isOneToOne: isOneToOne, mode: mode) DispatchQueue.main.async { - self.canUserRedactOtherUserIDReceivedInvocations.append(userID) - } - if let canUserRedactOtherUserIDClosure = canUserRedactOtherUserIDClosure { - return await canUserRedactOtherUserIDClosure(userID) - } else { - return canUserRedactOtherUserIDReturnValue + self.setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeReceivedInvocations.append((isEncrypted: isEncrypted, isOneToOne: isOneToOne, mode: mode)) } + try await setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeClosure?(isEncrypted, isOneToOne, mode) } - //MARK: - canUserRedactOwn + //MARK: - restoreDefaultNotificationMode - var canUserRedactOwnUserIDUnderlyingCallsCount = 0 - var canUserRedactOwnUserIDCallsCount: Int { + var restoreDefaultNotificationModeRoomIdThrowableError: Error? + var restoreDefaultNotificationModeRoomIdUnderlyingCallsCount = 0 + var restoreDefaultNotificationModeRoomIdCallsCount: Int { get { if Thread.isMainThread { - return canUserRedactOwnUserIDUnderlyingCallsCount + return restoreDefaultNotificationModeRoomIdUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = canUserRedactOwnUserIDUnderlyingCallsCount + returnValue = restoreDefaultNotificationModeRoomIdUnderlyingCallsCount } return returnValue! @@ -10221,29 +10660,44 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - canUserRedactOwnUserIDUnderlyingCallsCount = newValue + restoreDefaultNotificationModeRoomIdUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - canUserRedactOwnUserIDUnderlyingCallsCount = newValue + restoreDefaultNotificationModeRoomIdUnderlyingCallsCount = newValue } } } } - var canUserRedactOwnUserIDCalled: Bool { - return canUserRedactOwnUserIDCallsCount > 0 + var restoreDefaultNotificationModeRoomIdCalled: Bool { + return restoreDefaultNotificationModeRoomIdCallsCount > 0 } - var canUserRedactOwnUserIDReceivedUserID: String? - var canUserRedactOwnUserIDReceivedInvocations: [String] = [] + var restoreDefaultNotificationModeRoomIdReceivedRoomId: String? + var restoreDefaultNotificationModeRoomIdReceivedInvocations: [String] = [] + var restoreDefaultNotificationModeRoomIdClosure: ((String) async throws -> Void)? - var canUserRedactOwnUserIDUnderlyingReturnValue: Result! - var canUserRedactOwnUserIDReturnValue: Result! { + func restoreDefaultNotificationMode(roomId: String) async throws { + if let error = restoreDefaultNotificationModeRoomIdThrowableError { + throw error + } + restoreDefaultNotificationModeRoomIdCallsCount += 1 + restoreDefaultNotificationModeRoomIdReceivedRoomId = roomId + DispatchQueue.main.async { + self.restoreDefaultNotificationModeRoomIdReceivedInvocations.append(roomId) + } + try await restoreDefaultNotificationModeRoomIdClosure?(roomId) + } + //MARK: - unmuteRoom + + var unmuteRoomRoomIdIsEncryptedIsOneToOneThrowableError: Error? + var unmuteRoomRoomIdIsEncryptedIsOneToOneUnderlyingCallsCount = 0 + var unmuteRoomRoomIdIsEncryptedIsOneToOneCallsCount: Int { get { if Thread.isMainThread { - return canUserRedactOwnUserIDUnderlyingReturnValue + return unmuteRoomRoomIdIsEncryptedIsOneToOneUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = canUserRedactOwnUserIDUnderlyingReturnValue + returnValue = unmuteRoomRoomIdIsEncryptedIsOneToOneUnderlyingCallsCount } return returnValue! @@ -10251,39 +10705,44 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - canUserRedactOwnUserIDUnderlyingReturnValue = newValue + unmuteRoomRoomIdIsEncryptedIsOneToOneUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - canUserRedactOwnUserIDUnderlyingReturnValue = newValue + unmuteRoomRoomIdIsEncryptedIsOneToOneUnderlyingCallsCount = newValue } } } } - var canUserRedactOwnUserIDClosure: ((String) async -> Result)? + var unmuteRoomRoomIdIsEncryptedIsOneToOneCalled: Bool { + return unmuteRoomRoomIdIsEncryptedIsOneToOneCallsCount > 0 + } + var unmuteRoomRoomIdIsEncryptedIsOneToOneReceivedArguments: (roomId: String, isEncrypted: Bool, isOneToOne: Bool)? + var unmuteRoomRoomIdIsEncryptedIsOneToOneReceivedInvocations: [(roomId: String, isEncrypted: Bool, isOneToOne: Bool)] = [] + var unmuteRoomRoomIdIsEncryptedIsOneToOneClosure: ((String, Bool, Bool) async throws -> Void)? - func canUserRedactOwn(userID: String) async -> Result { - canUserRedactOwnUserIDCallsCount += 1 - canUserRedactOwnUserIDReceivedUserID = userID - DispatchQueue.main.async { - self.canUserRedactOwnUserIDReceivedInvocations.append(userID) + func unmuteRoom(roomId: String, isEncrypted: Bool, isOneToOne: Bool) async throws { + if let error = unmuteRoomRoomIdIsEncryptedIsOneToOneThrowableError { + throw error } - if let canUserRedactOwnUserIDClosure = canUserRedactOwnUserIDClosure { - return await canUserRedactOwnUserIDClosure(userID) - } else { - return canUserRedactOwnUserIDReturnValue + unmuteRoomRoomIdIsEncryptedIsOneToOneCallsCount += 1 + unmuteRoomRoomIdIsEncryptedIsOneToOneReceivedArguments = (roomId: roomId, isEncrypted: isEncrypted, isOneToOne: isOneToOne) + DispatchQueue.main.async { + self.unmuteRoomRoomIdIsEncryptedIsOneToOneReceivedInvocations.append((roomId: roomId, isEncrypted: isEncrypted, isOneToOne: isOneToOne)) } + try await unmuteRoomRoomIdIsEncryptedIsOneToOneClosure?(roomId, isEncrypted, isOneToOne) } - //MARK: - canUserKick + //MARK: - isRoomMentionEnabled - var canUserKickUserIDUnderlyingCallsCount = 0 - var canUserKickUserIDCallsCount: Int { + var isRoomMentionEnabledThrowableError: Error? + var isRoomMentionEnabledUnderlyingCallsCount = 0 + var isRoomMentionEnabledCallsCount: Int { get { if Thread.isMainThread { - return canUserKickUserIDUnderlyingCallsCount + return isRoomMentionEnabledUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = canUserKickUserIDUnderlyingCallsCount + returnValue = isRoomMentionEnabledUnderlyingCallsCount } return returnValue! @@ -10291,29 +10750,27 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - canUserKickUserIDUnderlyingCallsCount = newValue + isRoomMentionEnabledUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - canUserKickUserIDUnderlyingCallsCount = newValue + isRoomMentionEnabledUnderlyingCallsCount = newValue } } } } - var canUserKickUserIDCalled: Bool { - return canUserKickUserIDCallsCount > 0 + var isRoomMentionEnabledCalled: Bool { + return isRoomMentionEnabledCallsCount > 0 } - var canUserKickUserIDReceivedUserID: String? - var canUserKickUserIDReceivedInvocations: [String] = [] - var canUserKickUserIDUnderlyingReturnValue: Result! - var canUserKickUserIDReturnValue: Result! { + var isRoomMentionEnabledUnderlyingReturnValue: Bool! + var isRoomMentionEnabledReturnValue: Bool! { get { if Thread.isMainThread { - return canUserKickUserIDUnderlyingReturnValue + return isRoomMentionEnabledUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: Bool? = nil DispatchQueue.main.sync { - returnValue = canUserKickUserIDUnderlyingReturnValue + returnValue = isRoomMentionEnabledUnderlyingReturnValue } return returnValue! @@ -10321,39 +10778,39 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - canUserKickUserIDUnderlyingReturnValue = newValue + isRoomMentionEnabledUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - canUserKickUserIDUnderlyingReturnValue = newValue + isRoomMentionEnabledUnderlyingReturnValue = newValue } } } } - var canUserKickUserIDClosure: ((String) async -> Result)? + var isRoomMentionEnabledClosure: (() async throws -> Bool)? - func canUserKick(userID: String) async -> Result { - canUserKickUserIDCallsCount += 1 - canUserKickUserIDReceivedUserID = userID - DispatchQueue.main.async { - self.canUserKickUserIDReceivedInvocations.append(userID) + func isRoomMentionEnabled() async throws -> Bool { + if let error = isRoomMentionEnabledThrowableError { + throw error } - if let canUserKickUserIDClosure = canUserKickUserIDClosure { - return await canUserKickUserIDClosure(userID) + isRoomMentionEnabledCallsCount += 1 + if let isRoomMentionEnabledClosure = isRoomMentionEnabledClosure { + return try await isRoomMentionEnabledClosure() } else { - return canUserKickUserIDReturnValue + return isRoomMentionEnabledReturnValue } } - //MARK: - canUserBan + //MARK: - setRoomMentionEnabled - var canUserBanUserIDUnderlyingCallsCount = 0 - var canUserBanUserIDCallsCount: Int { + var setRoomMentionEnabledEnabledThrowableError: Error? + var setRoomMentionEnabledEnabledUnderlyingCallsCount = 0 + var setRoomMentionEnabledEnabledCallsCount: Int { get { if Thread.isMainThread { - return canUserBanUserIDUnderlyingCallsCount + return setRoomMentionEnabledEnabledUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = canUserBanUserIDUnderlyingCallsCount + returnValue = setRoomMentionEnabledEnabledUnderlyingCallsCount } return returnValue! @@ -10361,29 +10818,44 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - canUserBanUserIDUnderlyingCallsCount = newValue + setRoomMentionEnabledEnabledUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - canUserBanUserIDUnderlyingCallsCount = newValue + setRoomMentionEnabledEnabledUnderlyingCallsCount = newValue } } } } - var canUserBanUserIDCalled: Bool { - return canUserBanUserIDCallsCount > 0 + var setRoomMentionEnabledEnabledCalled: Bool { + return setRoomMentionEnabledEnabledCallsCount > 0 } - var canUserBanUserIDReceivedUserID: String? - var canUserBanUserIDReceivedInvocations: [String] = [] + var setRoomMentionEnabledEnabledReceivedEnabled: Bool? + var setRoomMentionEnabledEnabledReceivedInvocations: [Bool] = [] + var setRoomMentionEnabledEnabledClosure: ((Bool) async throws -> Void)? - var canUserBanUserIDUnderlyingReturnValue: Result! - var canUserBanUserIDReturnValue: Result! { + func setRoomMentionEnabled(enabled: Bool) async throws { + if let error = setRoomMentionEnabledEnabledThrowableError { + throw error + } + setRoomMentionEnabledEnabledCallsCount += 1 + setRoomMentionEnabledEnabledReceivedEnabled = enabled + DispatchQueue.main.async { + self.setRoomMentionEnabledEnabledReceivedInvocations.append(enabled) + } + try await setRoomMentionEnabledEnabledClosure?(enabled) + } + //MARK: - isCallEnabled + + var isCallEnabledThrowableError: Error? + var isCallEnabledUnderlyingCallsCount = 0 + var isCallEnabledCallsCount: Int { get { if Thread.isMainThread { - return canUserBanUserIDUnderlyingReturnValue + return isCallEnabledUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = canUserBanUserIDUnderlyingReturnValue + returnValue = isCallEnabledUnderlyingCallsCount } return returnValue! @@ -10391,39 +10863,27 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - canUserBanUserIDUnderlyingReturnValue = newValue + isCallEnabledUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - canUserBanUserIDUnderlyingReturnValue = newValue + isCallEnabledUnderlyingCallsCount = newValue } } } } - var canUserBanUserIDClosure: ((String) async -> Result)? - - func canUserBan(userID: String) async -> Result { - canUserBanUserIDCallsCount += 1 - canUserBanUserIDReceivedUserID = userID - DispatchQueue.main.async { - self.canUserBanUserIDReceivedInvocations.append(userID) - } - if let canUserBanUserIDClosure = canUserBanUserIDClosure { - return await canUserBanUserIDClosure(userID) - } else { - return canUserBanUserIDReturnValue - } + var isCallEnabledCalled: Bool { + return isCallEnabledCallsCount > 0 } - //MARK: - canUserTriggerRoomNotification - var canUserTriggerRoomNotificationUserIDUnderlyingCallsCount = 0 - var canUserTriggerRoomNotificationUserIDCallsCount: Int { + var isCallEnabledUnderlyingReturnValue: Bool! + var isCallEnabledReturnValue: Bool! { get { if Thread.isMainThread { - return canUserTriggerRoomNotificationUserIDUnderlyingCallsCount + return isCallEnabledUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Bool? = nil DispatchQueue.main.sync { - returnValue = canUserTriggerRoomNotificationUserIDUnderlyingCallsCount + returnValue = isCallEnabledUnderlyingReturnValue } return returnValue! @@ -10431,29 +10891,39 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - canUserTriggerRoomNotificationUserIDUnderlyingCallsCount = newValue + isCallEnabledUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - canUserTriggerRoomNotificationUserIDUnderlyingCallsCount = newValue + isCallEnabledUnderlyingReturnValue = newValue } } } } - var canUserTriggerRoomNotificationUserIDCalled: Bool { - return canUserTriggerRoomNotificationUserIDCallsCount > 0 + var isCallEnabledClosure: (() async throws -> Bool)? + + func isCallEnabled() async throws -> Bool { + if let error = isCallEnabledThrowableError { + throw error + } + isCallEnabledCallsCount += 1 + if let isCallEnabledClosure = isCallEnabledClosure { + return try await isCallEnabledClosure() + } else { + return isCallEnabledReturnValue + } } - var canUserTriggerRoomNotificationUserIDReceivedUserID: String? - var canUserTriggerRoomNotificationUserIDReceivedInvocations: [String] = [] + //MARK: - setCallEnabled - var canUserTriggerRoomNotificationUserIDUnderlyingReturnValue: Result! - var canUserTriggerRoomNotificationUserIDReturnValue: Result! { + var setCallEnabledEnabledThrowableError: Error? + var setCallEnabledEnabledUnderlyingCallsCount = 0 + var setCallEnabledEnabledCallsCount: Int { get { if Thread.isMainThread { - return canUserTriggerRoomNotificationUserIDUnderlyingReturnValue + return setCallEnabledEnabledUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = canUserTriggerRoomNotificationUserIDUnderlyingReturnValue + returnValue = setCallEnabledEnabledUnderlyingCallsCount } return returnValue! @@ -10461,39 +10931,44 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - canUserTriggerRoomNotificationUserIDUnderlyingReturnValue = newValue + setCallEnabledEnabledUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - canUserTriggerRoomNotificationUserIDUnderlyingReturnValue = newValue + setCallEnabledEnabledUnderlyingCallsCount = newValue } } } } - var canUserTriggerRoomNotificationUserIDClosure: ((String) async -> Result)? + var setCallEnabledEnabledCalled: Bool { + return setCallEnabledEnabledCallsCount > 0 + } + var setCallEnabledEnabledReceivedEnabled: Bool? + var setCallEnabledEnabledReceivedInvocations: [Bool] = [] + var setCallEnabledEnabledClosure: ((Bool) async throws -> Void)? - func canUserTriggerRoomNotification(userID: String) async -> Result { - canUserTriggerRoomNotificationUserIDCallsCount += 1 - canUserTriggerRoomNotificationUserIDReceivedUserID = userID - DispatchQueue.main.async { - self.canUserTriggerRoomNotificationUserIDReceivedInvocations.append(userID) + func setCallEnabled(enabled: Bool) async throws { + if let error = setCallEnabledEnabledThrowableError { + throw error } - if let canUserTriggerRoomNotificationUserIDClosure = canUserTriggerRoomNotificationUserIDClosure { - return await canUserTriggerRoomNotificationUserIDClosure(userID) - } else { - return canUserTriggerRoomNotificationUserIDReturnValue + setCallEnabledEnabledCallsCount += 1 + setCallEnabledEnabledReceivedEnabled = enabled + DispatchQueue.main.async { + self.setCallEnabledEnabledReceivedInvocations.append(enabled) } + try await setCallEnabledEnabledClosure?(enabled) } - //MARK: - canUserPinOrUnpin + //MARK: - isInviteForMeEnabled - var canUserPinOrUnpinUserIDUnderlyingCallsCount = 0 - var canUserPinOrUnpinUserIDCallsCount: Int { + var isInviteForMeEnabledThrowableError: Error? + var isInviteForMeEnabledUnderlyingCallsCount = 0 + var isInviteForMeEnabledCallsCount: Int { get { if Thread.isMainThread { - return canUserPinOrUnpinUserIDUnderlyingCallsCount + return isInviteForMeEnabledUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = canUserPinOrUnpinUserIDUnderlyingCallsCount + returnValue = isInviteForMeEnabledUnderlyingCallsCount } return returnValue! @@ -10501,29 +10976,27 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - canUserPinOrUnpinUserIDUnderlyingCallsCount = newValue + isInviteForMeEnabledUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - canUserPinOrUnpinUserIDUnderlyingCallsCount = newValue + isInviteForMeEnabledUnderlyingCallsCount = newValue } } } } - var canUserPinOrUnpinUserIDCalled: Bool { - return canUserPinOrUnpinUserIDCallsCount > 0 + var isInviteForMeEnabledCalled: Bool { + return isInviteForMeEnabledCallsCount > 0 } - var canUserPinOrUnpinUserIDReceivedUserID: String? - var canUserPinOrUnpinUserIDReceivedInvocations: [String] = [] - var canUserPinOrUnpinUserIDUnderlyingReturnValue: Result! - var canUserPinOrUnpinUserIDReturnValue: Result! { + var isInviteForMeEnabledUnderlyingReturnValue: Bool! + var isInviteForMeEnabledReturnValue: Bool! { get { if Thread.isMainThread { - return canUserPinOrUnpinUserIDUnderlyingReturnValue + return isInviteForMeEnabledUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: Bool? = nil DispatchQueue.main.sync { - returnValue = canUserPinOrUnpinUserIDUnderlyingReturnValue + returnValue = isInviteForMeEnabledUnderlyingReturnValue } return returnValue! @@ -10531,39 +11004,39 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - canUserPinOrUnpinUserIDUnderlyingReturnValue = newValue + isInviteForMeEnabledUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - canUserPinOrUnpinUserIDUnderlyingReturnValue = newValue + isInviteForMeEnabledUnderlyingReturnValue = newValue } } } } - var canUserPinOrUnpinUserIDClosure: ((String) async -> Result)? + var isInviteForMeEnabledClosure: (() async throws -> Bool)? - func canUserPinOrUnpin(userID: String) async -> Result { - canUserPinOrUnpinUserIDCallsCount += 1 - canUserPinOrUnpinUserIDReceivedUserID = userID - DispatchQueue.main.async { - self.canUserPinOrUnpinUserIDReceivedInvocations.append(userID) + func isInviteForMeEnabled() async throws -> Bool { + if let error = isInviteForMeEnabledThrowableError { + throw error } - if let canUserPinOrUnpinUserIDClosure = canUserPinOrUnpinUserIDClosure { - return await canUserPinOrUnpinUserIDClosure(userID) + isInviteForMeEnabledCallsCount += 1 + if let isInviteForMeEnabledClosure = isInviteForMeEnabledClosure { + return try await isInviteForMeEnabledClosure() } else { - return canUserPinOrUnpinUserIDReturnValue + return isInviteForMeEnabledReturnValue } } - //MARK: - kickUser + //MARK: - setInviteForMeEnabled - var kickUserUnderlyingCallsCount = 0 - var kickUserCallsCount: Int { + var setInviteForMeEnabledEnabledThrowableError: Error? + var setInviteForMeEnabledEnabledUnderlyingCallsCount = 0 + var setInviteForMeEnabledEnabledCallsCount: Int { get { if Thread.isMainThread { - return kickUserUnderlyingCallsCount + return setInviteForMeEnabledEnabledUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = kickUserUnderlyingCallsCount + returnValue = setInviteForMeEnabledEnabledUnderlyingCallsCount } return returnValue! @@ -10571,29 +11044,44 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - kickUserUnderlyingCallsCount = newValue + setInviteForMeEnabledEnabledUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - kickUserUnderlyingCallsCount = newValue + setInviteForMeEnabledEnabledUnderlyingCallsCount = newValue } } } } - var kickUserCalled: Bool { - return kickUserCallsCount > 0 + var setInviteForMeEnabledEnabledCalled: Bool { + return setInviteForMeEnabledEnabledCallsCount > 0 } - var kickUserReceivedUserID: String? - var kickUserReceivedInvocations: [String] = [] + var setInviteForMeEnabledEnabledReceivedEnabled: Bool? + var setInviteForMeEnabledEnabledReceivedInvocations: [Bool] = [] + var setInviteForMeEnabledEnabledClosure: ((Bool) async throws -> Void)? - var kickUserUnderlyingReturnValue: Result! - var kickUserReturnValue: Result! { + func setInviteForMeEnabled(enabled: Bool) async throws { + if let error = setInviteForMeEnabledEnabledThrowableError { + throw error + } + setInviteForMeEnabledEnabledCallsCount += 1 + setInviteForMeEnabledEnabledReceivedEnabled = enabled + DispatchQueue.main.async { + self.setInviteForMeEnabledEnabledReceivedInvocations.append(enabled) + } + try await setInviteForMeEnabledEnabledClosure?(enabled) + } + //MARK: - getRoomsWithUserDefinedRules + + var getRoomsWithUserDefinedRulesThrowableError: Error? + var getRoomsWithUserDefinedRulesUnderlyingCallsCount = 0 + var getRoomsWithUserDefinedRulesCallsCount: Int { get { if Thread.isMainThread { - return kickUserUnderlyingReturnValue + return getRoomsWithUserDefinedRulesUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = kickUserUnderlyingReturnValue + returnValue = getRoomsWithUserDefinedRulesUnderlyingCallsCount } return returnValue! @@ -10601,39 +11089,27 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - kickUserUnderlyingReturnValue = newValue + getRoomsWithUserDefinedRulesUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - kickUserUnderlyingReturnValue = newValue + getRoomsWithUserDefinedRulesUnderlyingCallsCount = newValue } } } } - var kickUserClosure: ((String) async -> Result)? - - func kickUser(_ userID: String) async -> Result { - kickUserCallsCount += 1 - kickUserReceivedUserID = userID - DispatchQueue.main.async { - self.kickUserReceivedInvocations.append(userID) - } - if let kickUserClosure = kickUserClosure { - return await kickUserClosure(userID) - } else { - return kickUserReturnValue - } + var getRoomsWithUserDefinedRulesCalled: Bool { + return getRoomsWithUserDefinedRulesCallsCount > 0 } - //MARK: - banUser - var banUserUnderlyingCallsCount = 0 - var banUserCallsCount: Int { + var getRoomsWithUserDefinedRulesUnderlyingReturnValue: [String]! + var getRoomsWithUserDefinedRulesReturnValue: [String]! { get { if Thread.isMainThread { - return banUserUnderlyingCallsCount + return getRoomsWithUserDefinedRulesUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: [String]? = nil DispatchQueue.main.sync { - returnValue = banUserUnderlyingCallsCount + returnValue = getRoomsWithUserDefinedRulesUnderlyingReturnValue } return returnValue! @@ -10641,29 +11117,38 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - banUserUnderlyingCallsCount = newValue + getRoomsWithUserDefinedRulesUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - banUserUnderlyingCallsCount = newValue + getRoomsWithUserDefinedRulesUnderlyingReturnValue = newValue } } } } - var banUserCalled: Bool { - return banUserCallsCount > 0 + var getRoomsWithUserDefinedRulesClosure: (() async throws -> [String])? + + func getRoomsWithUserDefinedRules() async throws -> [String] { + if let error = getRoomsWithUserDefinedRulesThrowableError { + throw error + } + getRoomsWithUserDefinedRulesCallsCount += 1 + if let getRoomsWithUserDefinedRulesClosure = getRoomsWithUserDefinedRulesClosure { + return try await getRoomsWithUserDefinedRulesClosure() + } else { + return getRoomsWithUserDefinedRulesReturnValue + } } - var banUserReceivedUserID: String? - var banUserReceivedInvocations: [String] = [] + //MARK: - canPushEncryptedEventsToDevice - var banUserUnderlyingReturnValue: Result! - var banUserReturnValue: Result! { + var canPushEncryptedEventsToDeviceUnderlyingCallsCount = 0 + var canPushEncryptedEventsToDeviceCallsCount: Int { get { if Thread.isMainThread { - return banUserUnderlyingReturnValue + return canPushEncryptedEventsToDeviceUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = banUserUnderlyingReturnValue + returnValue = canPushEncryptedEventsToDeviceUnderlyingCallsCount } return returnValue! @@ -10671,39 +11156,27 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - banUserUnderlyingReturnValue = newValue + canPushEncryptedEventsToDeviceUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - banUserUnderlyingReturnValue = newValue + canPushEncryptedEventsToDeviceUnderlyingCallsCount = newValue } } } } - var banUserClosure: ((String) async -> Result)? - - func banUser(_ userID: String) async -> Result { - banUserCallsCount += 1 - banUserReceivedUserID = userID - DispatchQueue.main.async { - self.banUserReceivedInvocations.append(userID) - } - if let banUserClosure = banUserClosure { - return await banUserClosure(userID) - } else { - return banUserReturnValue - } + var canPushEncryptedEventsToDeviceCalled: Bool { + return canPushEncryptedEventsToDeviceCallsCount > 0 } - //MARK: - unbanUser - var unbanUserUnderlyingCallsCount = 0 - var unbanUserCallsCount: Int { + var canPushEncryptedEventsToDeviceUnderlyingReturnValue: Bool! + var canPushEncryptedEventsToDeviceReturnValue: Bool! { get { if Thread.isMainThread { - return unbanUserUnderlyingCallsCount + return canPushEncryptedEventsToDeviceUnderlyingReturnValue } else { - var returnValue: Int? = nil + var returnValue: Bool? = nil DispatchQueue.main.sync { - returnValue = unbanUserUnderlyingCallsCount + returnValue = canPushEncryptedEventsToDeviceUnderlyingReturnValue } return returnValue! @@ -10711,29 +11184,38 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - unbanUserUnderlyingCallsCount = newValue + canPushEncryptedEventsToDeviceUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - unbanUserUnderlyingCallsCount = newValue + canPushEncryptedEventsToDeviceUnderlyingReturnValue = newValue } } } } - var unbanUserCalled: Bool { - return unbanUserCallsCount > 0 + var canPushEncryptedEventsToDeviceClosure: (() async -> Bool)? + + func canPushEncryptedEventsToDevice() async -> Bool { + canPushEncryptedEventsToDeviceCallsCount += 1 + if let canPushEncryptedEventsToDeviceClosure = canPushEncryptedEventsToDeviceClosure { + return await canPushEncryptedEventsToDeviceClosure() + } else { + return canPushEncryptedEventsToDeviceReturnValue + } } - var unbanUserReceivedUserID: String? - var unbanUserReceivedInvocations: [String] = [] +} +class OrientationManagerMock: OrientationManagerProtocol { - var unbanUserUnderlyingReturnValue: Result! - var unbanUserReturnValue: Result! { + //MARK: - setOrientation + + var setOrientationUnderlyingCallsCount = 0 + var setOrientationCallsCount: Int { get { if Thread.isMainThread { - return unbanUserUnderlyingReturnValue + return setOrientationUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = unbanUserUnderlyingReturnValue + returnValue = setOrientationUnderlyingCallsCount } return returnValue! @@ -10741,39 +11223,40 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - unbanUserUnderlyingReturnValue = newValue + setOrientationUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - unbanUserUnderlyingReturnValue = newValue + setOrientationUnderlyingCallsCount = newValue } } } } - var unbanUserClosure: ((String) async -> Result)? + var setOrientationCalled: Bool { + return setOrientationCallsCount > 0 + } + var setOrientationReceivedOrientation: UIInterfaceOrientationMask? + var setOrientationReceivedInvocations: [UIInterfaceOrientationMask] = [] + var setOrientationClosure: ((UIInterfaceOrientationMask) -> Void)? - func unbanUser(_ userID: String) async -> Result { - unbanUserCallsCount += 1 - unbanUserReceivedUserID = userID + func setOrientation(_ orientation: UIInterfaceOrientationMask) { + setOrientationCallsCount += 1 + setOrientationReceivedOrientation = orientation DispatchQueue.main.async { - self.unbanUserReceivedInvocations.append(userID) - } - if let unbanUserClosure = unbanUserClosure { - return await unbanUserClosure(userID) - } else { - return unbanUserReturnValue + self.setOrientationReceivedInvocations.append(orientation) } + setOrientationClosure?(orientation) } - //MARK: - canUserJoinCall + //MARK: - lockOrientation - var canUserJoinCallUserIDUnderlyingCallsCount = 0 - var canUserJoinCallUserIDCallsCount: Int { + var lockOrientationUnderlyingCallsCount = 0 + var lockOrientationCallsCount: Int { get { if Thread.isMainThread { - return canUserJoinCallUserIDUnderlyingCallsCount + return lockOrientationUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = canUserJoinCallUserIDUnderlyingCallsCount + returnValue = lockOrientationUnderlyingCallsCount } return returnValue! @@ -10781,29 +11264,43 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - canUserJoinCallUserIDUnderlyingCallsCount = newValue + lockOrientationUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - canUserJoinCallUserIDUnderlyingCallsCount = newValue + lockOrientationUnderlyingCallsCount = newValue } } } } - var canUserJoinCallUserIDCalled: Bool { - return canUserJoinCallUserIDCallsCount > 0 + var lockOrientationCalled: Bool { + return lockOrientationCallsCount > 0 } - var canUserJoinCallUserIDReceivedUserID: String? - var canUserJoinCallUserIDReceivedInvocations: [String] = [] + var lockOrientationReceivedOrientation: UIInterfaceOrientationMask? + var lockOrientationReceivedInvocations: [UIInterfaceOrientationMask] = [] + var lockOrientationClosure: ((UIInterfaceOrientationMask) -> Void)? - var canUserJoinCallUserIDUnderlyingReturnValue: Result! - var canUserJoinCallUserIDReturnValue: Result! { + func lockOrientation(_ orientation: UIInterfaceOrientationMask) { + lockOrientationCallsCount += 1 + lockOrientationReceivedOrientation = orientation + DispatchQueue.main.async { + self.lockOrientationReceivedInvocations.append(orientation) + } + lockOrientationClosure?(orientation) + } +} +class PHGPostHogMock: PHGPostHogProtocol { + + //MARK: - optIn + + var optInUnderlyingCallsCount = 0 + var optInCallsCount: Int { get { if Thread.isMainThread { - return canUserJoinCallUserIDUnderlyingReturnValue + return optInUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = canUserJoinCallUserIDUnderlyingReturnValue + returnValue = optInUnderlyingCallsCount } return returnValue! @@ -10811,39 +11308,34 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - canUserJoinCallUserIDUnderlyingReturnValue = newValue + optInUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - canUserJoinCallUserIDUnderlyingReturnValue = newValue + optInUnderlyingCallsCount = newValue } } } } - var canUserJoinCallUserIDClosure: ((String) async -> Result)? - - func canUserJoinCall(userID: String) async -> Result { - canUserJoinCallUserIDCallsCount += 1 - canUserJoinCallUserIDReceivedUserID = userID - DispatchQueue.main.async { - self.canUserJoinCallUserIDReceivedInvocations.append(userID) - } - if let canUserJoinCallUserIDClosure = canUserJoinCallUserIDClosure { - return await canUserJoinCallUserIDClosure(userID) - } else { - return canUserJoinCallUserIDReturnValue - } + var optInCalled: Bool { + return optInCallsCount > 0 } - //MARK: - elementCallWidgetDriver + var optInClosure: (() -> Void)? - var elementCallWidgetDriverDeviceIDUnderlyingCallsCount = 0 - var elementCallWidgetDriverDeviceIDCallsCount: Int { + func optIn() { + optInCallsCount += 1 + optInClosure?() + } + //MARK: - optOut + + var optOutUnderlyingCallsCount = 0 + var optOutCallsCount: Int { get { if Thread.isMainThread { - return elementCallWidgetDriverDeviceIDUnderlyingCallsCount + return optOutUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = elementCallWidgetDriverDeviceIDUnderlyingCallsCount + returnValue = optOutUnderlyingCallsCount } return returnValue! @@ -10851,29 +11343,34 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - elementCallWidgetDriverDeviceIDUnderlyingCallsCount = newValue + optOutUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - elementCallWidgetDriverDeviceIDUnderlyingCallsCount = newValue + optOutUnderlyingCallsCount = newValue } } } } - var elementCallWidgetDriverDeviceIDCalled: Bool { - return elementCallWidgetDriverDeviceIDCallsCount > 0 + var optOutCalled: Bool { + return optOutCallsCount > 0 } - var elementCallWidgetDriverDeviceIDReceivedDeviceID: String? - var elementCallWidgetDriverDeviceIDReceivedInvocations: [String] = [] + var optOutClosure: (() -> Void)? - var elementCallWidgetDriverDeviceIDUnderlyingReturnValue: ElementCallWidgetDriverProtocol! - var elementCallWidgetDriverDeviceIDReturnValue: ElementCallWidgetDriverProtocol! { + func optOut() { + optOutCallsCount += 1 + optOutClosure?() + } + //MARK: - reset + + var resetUnderlyingCallsCount = 0 + var resetCallsCount: Int { get { if Thread.isMainThread { - return elementCallWidgetDriverDeviceIDUnderlyingReturnValue + return resetUnderlyingCallsCount } else { - var returnValue: ElementCallWidgetDriverProtocol? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = elementCallWidgetDriverDeviceIDUnderlyingReturnValue + returnValue = resetUnderlyingCallsCount } return returnValue! @@ -10881,39 +11378,34 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - elementCallWidgetDriverDeviceIDUnderlyingReturnValue = newValue + resetUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - elementCallWidgetDriverDeviceIDUnderlyingReturnValue = newValue + resetUnderlyingCallsCount = newValue } } } } - var elementCallWidgetDriverDeviceIDClosure: ((String) -> ElementCallWidgetDriverProtocol)? + var resetCalled: Bool { + return resetCallsCount > 0 + } + var resetClosure: (() -> Void)? - func elementCallWidgetDriver(deviceID: String) -> ElementCallWidgetDriverProtocol { - elementCallWidgetDriverDeviceIDCallsCount += 1 - elementCallWidgetDriverDeviceIDReceivedDeviceID = deviceID - DispatchQueue.main.async { - self.elementCallWidgetDriverDeviceIDReceivedInvocations.append(deviceID) - } - if let elementCallWidgetDriverDeviceIDClosure = elementCallWidgetDriverDeviceIDClosure { - return elementCallWidgetDriverDeviceIDClosure(deviceID) - } else { - return elementCallWidgetDriverDeviceIDReturnValue - } + func reset() { + resetCallsCount += 1 + resetClosure?() } - //MARK: - sendCallNotificationIfNeeeded + //MARK: - capture - var sendCallNotificationIfNeeededUnderlyingCallsCount = 0 - var sendCallNotificationIfNeeededCallsCount: Int { + var capturePropertiesUserPropertiesUnderlyingCallsCount = 0 + var capturePropertiesUserPropertiesCallsCount: Int { get { if Thread.isMainThread { - return sendCallNotificationIfNeeededUnderlyingCallsCount + return capturePropertiesUserPropertiesUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = sendCallNotificationIfNeeededUnderlyingCallsCount + returnValue = capturePropertiesUserPropertiesUnderlyingCallsCount } return returnValue! @@ -10921,27 +11413,40 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - sendCallNotificationIfNeeededUnderlyingCallsCount = newValue + capturePropertiesUserPropertiesUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - sendCallNotificationIfNeeededUnderlyingCallsCount = newValue + capturePropertiesUserPropertiesUnderlyingCallsCount = newValue } } } } - var sendCallNotificationIfNeeededCalled: Bool { - return sendCallNotificationIfNeeededCallsCount > 0 + var capturePropertiesUserPropertiesCalled: Bool { + return capturePropertiesUserPropertiesCallsCount > 0 + } + var capturePropertiesUserPropertiesReceivedArguments: (event: String, properties: [String: Any]?, userProperties: [String: Any]?)? + var capturePropertiesUserPropertiesReceivedInvocations: [(event: String, properties: [String: Any]?, userProperties: [String: Any]?)] = [] + var capturePropertiesUserPropertiesClosure: ((String, [String: Any]?, [String: Any]?) -> Void)? + + func capture(_ event: String, properties: [String: Any]?, userProperties: [String: Any]?) { + capturePropertiesUserPropertiesCallsCount += 1 + capturePropertiesUserPropertiesReceivedArguments = (event: event, properties: properties, userProperties: userProperties) + DispatchQueue.main.async { + self.capturePropertiesUserPropertiesReceivedInvocations.append((event: event, properties: properties, userProperties: userProperties)) + } + capturePropertiesUserPropertiesClosure?(event, properties, userProperties) } + //MARK: - screen - var sendCallNotificationIfNeeededUnderlyingReturnValue: Result! - var sendCallNotificationIfNeeededReturnValue: Result! { + var screenPropertiesUnderlyingCallsCount = 0 + var screenPropertiesCallsCount: Int { get { if Thread.isMainThread { - return sendCallNotificationIfNeeededUnderlyingReturnValue + return screenPropertiesUnderlyingCallsCount } else { - var returnValue: Result? = nil + var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = sendCallNotificationIfNeeededUnderlyingReturnValue + returnValue = screenPropertiesUnderlyingCallsCount } return returnValue! @@ -10949,35 +11454,43 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - sendCallNotificationIfNeeededUnderlyingReturnValue = newValue + screenPropertiesUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - sendCallNotificationIfNeeededUnderlyingReturnValue = newValue + screenPropertiesUnderlyingCallsCount = newValue } } } } - var sendCallNotificationIfNeeededClosure: (() async -> Result)? + var screenPropertiesCalled: Bool { + return screenPropertiesCallsCount > 0 + } + var screenPropertiesReceivedArguments: (screenTitle: String, properties: [String: Any]?)? + var screenPropertiesReceivedInvocations: [(screenTitle: String, properties: [String: Any]?)] = [] + var screenPropertiesClosure: ((String, [String: Any]?) -> Void)? - func sendCallNotificationIfNeeeded() async -> Result { - sendCallNotificationIfNeeededCallsCount += 1 - if let sendCallNotificationIfNeeededClosure = sendCallNotificationIfNeeededClosure { - return await sendCallNotificationIfNeeededClosure() - } else { - return sendCallNotificationIfNeeededReturnValue + func screen(_ screenTitle: String, properties: [String: Any]?) { + screenPropertiesCallsCount += 1 + screenPropertiesReceivedArguments = (screenTitle: screenTitle, properties: properties) + DispatchQueue.main.async { + self.screenPropertiesReceivedInvocations.append((screenTitle: screenTitle, properties: properties)) } + screenPropertiesClosure?(screenTitle, properties) } - //MARK: - matrixToPermalink +} +class PollInteractionHandlerMock: PollInteractionHandlerProtocol { - var matrixToPermalinkUnderlyingCallsCount = 0 - var matrixToPermalinkCallsCount: Int { + //MARK: - sendPollResponse + + var sendPollResponsePollStartIDOptionIDUnderlyingCallsCount = 0 + var sendPollResponsePollStartIDOptionIDCallsCount: Int { get { if Thread.isMainThread { - return matrixToPermalinkUnderlyingCallsCount + return sendPollResponsePollStartIDOptionIDUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = matrixToPermalinkUnderlyingCallsCount + returnValue = sendPollResponsePollStartIDOptionIDUnderlyingCallsCount } return returnValue! @@ -10985,27 +11498,29 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - matrixToPermalinkUnderlyingCallsCount = newValue + sendPollResponsePollStartIDOptionIDUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - matrixToPermalinkUnderlyingCallsCount = newValue + sendPollResponsePollStartIDOptionIDUnderlyingCallsCount = newValue } } } } - var matrixToPermalinkCalled: Bool { - return matrixToPermalinkCallsCount > 0 + var sendPollResponsePollStartIDOptionIDCalled: Bool { + return sendPollResponsePollStartIDOptionIDCallsCount > 0 } + var sendPollResponsePollStartIDOptionIDReceivedArguments: (pollStartID: String, optionID: String)? + var sendPollResponsePollStartIDOptionIDReceivedInvocations: [(pollStartID: String, optionID: String)] = [] - var matrixToPermalinkUnderlyingReturnValue: Result! - var matrixToPermalinkReturnValue: Result! { + var sendPollResponsePollStartIDOptionIDUnderlyingReturnValue: Result! + var sendPollResponsePollStartIDOptionIDReturnValue: Result! { get { if Thread.isMainThread { - return matrixToPermalinkUnderlyingReturnValue + return sendPollResponsePollStartIDOptionIDUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = matrixToPermalinkUnderlyingReturnValue + returnValue = sendPollResponsePollStartIDOptionIDUnderlyingReturnValue } return returnValue! @@ -11013,35 +11528,39 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - matrixToPermalinkUnderlyingReturnValue = newValue + sendPollResponsePollStartIDOptionIDUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - matrixToPermalinkUnderlyingReturnValue = newValue + sendPollResponsePollStartIDOptionIDUnderlyingReturnValue = newValue } } } } - var matrixToPermalinkClosure: (() async -> Result)? + var sendPollResponsePollStartIDOptionIDClosure: ((String, String) async -> Result)? - func matrixToPermalink() async -> Result { - matrixToPermalinkCallsCount += 1 - if let matrixToPermalinkClosure = matrixToPermalinkClosure { - return await matrixToPermalinkClosure() + func sendPollResponse(pollStartID: String, optionID: String) async -> Result { + sendPollResponsePollStartIDOptionIDCallsCount += 1 + sendPollResponsePollStartIDOptionIDReceivedArguments = (pollStartID: pollStartID, optionID: optionID) + DispatchQueue.main.async { + self.sendPollResponsePollStartIDOptionIDReceivedInvocations.append((pollStartID: pollStartID, optionID: optionID)) + } + if let sendPollResponsePollStartIDOptionIDClosure = sendPollResponsePollStartIDOptionIDClosure { + return await sendPollResponsePollStartIDOptionIDClosure(pollStartID, optionID) } else { - return matrixToPermalinkReturnValue + return sendPollResponsePollStartIDOptionIDReturnValue } } - //MARK: - matrixToEventPermalink + //MARK: - endPoll - var matrixToEventPermalinkUnderlyingCallsCount = 0 - var matrixToEventPermalinkCallsCount: Int { + var endPollPollStartIDUnderlyingCallsCount = 0 + var endPollPollStartIDCallsCount: Int { get { if Thread.isMainThread { - return matrixToEventPermalinkUnderlyingCallsCount + return endPollPollStartIDUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = matrixToEventPermalinkUnderlyingCallsCount + returnValue = endPollPollStartIDUnderlyingCallsCount } return returnValue! @@ -11049,29 +11568,29 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - matrixToEventPermalinkUnderlyingCallsCount = newValue + endPollPollStartIDUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - matrixToEventPermalinkUnderlyingCallsCount = newValue + endPollPollStartIDUnderlyingCallsCount = newValue } } } } - var matrixToEventPermalinkCalled: Bool { - return matrixToEventPermalinkCallsCount > 0 + var endPollPollStartIDCalled: Bool { + return endPollPollStartIDCallsCount > 0 } - var matrixToEventPermalinkReceivedEventID: String? - var matrixToEventPermalinkReceivedInvocations: [String] = [] + var endPollPollStartIDReceivedPollStartID: String? + var endPollPollStartIDReceivedInvocations: [String] = [] - var matrixToEventPermalinkUnderlyingReturnValue: Result! - var matrixToEventPermalinkReturnValue: Result! { + var endPollPollStartIDUnderlyingReturnValue: Result! + var endPollPollStartIDReturnValue: Result! { get { if Thread.isMainThread { - return matrixToEventPermalinkUnderlyingReturnValue + return endPollPollStartIDUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = matrixToEventPermalinkUnderlyingReturnValue + returnValue = endPollPollStartIDUnderlyingReturnValue } return returnValue! @@ -11079,39 +11598,47 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - matrixToEventPermalinkUnderlyingReturnValue = newValue + endPollPollStartIDUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - matrixToEventPermalinkUnderlyingReturnValue = newValue + endPollPollStartIDUnderlyingReturnValue = newValue } } } } - var matrixToEventPermalinkClosure: ((String) async -> Result)? + var endPollPollStartIDClosure: ((String) async -> Result)? - func matrixToEventPermalink(_ eventID: String) async -> Result { - matrixToEventPermalinkCallsCount += 1 - matrixToEventPermalinkReceivedEventID = eventID + func endPoll(pollStartID: String) async -> Result { + endPollPollStartIDCallsCount += 1 + endPollPollStartIDReceivedPollStartID = pollStartID DispatchQueue.main.async { - self.matrixToEventPermalinkReceivedInvocations.append(eventID) + self.endPollPollStartIDReceivedInvocations.append(pollStartID) } - if let matrixToEventPermalinkClosure = matrixToEventPermalinkClosure { - return await matrixToEventPermalinkClosure(eventID) + if let endPollPollStartIDClosure = endPollPollStartIDClosure { + return await endPollPollStartIDClosure(pollStartID) } else { - return matrixToEventPermalinkReturnValue + return endPollPollStartIDReturnValue } } - //MARK: - saveDraft +} +class QRCodeLoginServiceMock: QRCodeLoginServiceProtocol { + var qrLoginProgressPublisher: AnyPublisher { + get { return underlyingQrLoginProgressPublisher } + set(value) { underlyingQrLoginProgressPublisher = value } + } + var underlyingQrLoginProgressPublisher: AnyPublisher! - var saveDraftUnderlyingCallsCount = 0 - var saveDraftCallsCount: Int { + //MARK: - loginWithQRCode + + var loginWithQRCodeDataUnderlyingCallsCount = 0 + var loginWithQRCodeDataCallsCount: Int { get { if Thread.isMainThread { - return saveDraftUnderlyingCallsCount + return loginWithQRCodeDataUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = saveDraftUnderlyingCallsCount + returnValue = loginWithQRCodeDataUnderlyingCallsCount } return returnValue! @@ -11119,29 +11646,29 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - saveDraftUnderlyingCallsCount = newValue + loginWithQRCodeDataUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - saveDraftUnderlyingCallsCount = newValue + loginWithQRCodeDataUnderlyingCallsCount = newValue } } } } - var saveDraftCalled: Bool { - return saveDraftCallsCount > 0 + var loginWithQRCodeDataCalled: Bool { + return loginWithQRCodeDataCallsCount > 0 } - var saveDraftReceivedDraft: ComposerDraft? - var saveDraftReceivedInvocations: [ComposerDraft] = [] + var loginWithQRCodeDataReceivedData: Data? + var loginWithQRCodeDataReceivedInvocations: [Data] = [] - var saveDraftUnderlyingReturnValue: Result! - var saveDraftReturnValue: Result! { + var loginWithQRCodeDataUnderlyingReturnValue: Result! + var loginWithQRCodeDataReturnValue: Result! { get { if Thread.isMainThread { - return saveDraftUnderlyingReturnValue + return loginWithQRCodeDataUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = saveDraftUnderlyingReturnValue + returnValue = loginWithQRCodeDataUnderlyingReturnValue } return returnValue! @@ -11149,39 +11676,47 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - saveDraftUnderlyingReturnValue = newValue + loginWithQRCodeDataUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - saveDraftUnderlyingReturnValue = newValue + loginWithQRCodeDataUnderlyingReturnValue = newValue } } } } - var saveDraftClosure: ((ComposerDraft) async -> Result)? + var loginWithQRCodeDataClosure: ((Data) async -> Result)? - func saveDraft(_ draft: ComposerDraft) async -> Result { - saveDraftCallsCount += 1 - saveDraftReceivedDraft = draft + func loginWithQRCode(data: Data) async -> Result { + loginWithQRCodeDataCallsCount += 1 + loginWithQRCodeDataReceivedData = data DispatchQueue.main.async { - self.saveDraftReceivedInvocations.append(draft) + self.loginWithQRCodeDataReceivedInvocations.append(data) } - if let saveDraftClosure = saveDraftClosure { - return await saveDraftClosure(draft) + if let loginWithQRCodeDataClosure = loginWithQRCodeDataClosure { + return await loginWithQRCodeDataClosure(data) } else { - return saveDraftReturnValue + return loginWithQRCodeDataReturnValue } } - //MARK: - loadDraft +} +class RoomDirectorySearchProxyMock: RoomDirectorySearchProxyProtocol { + var resultsPublisher: CurrentValuePublisher<[RoomDirectorySearchResult], Never> { + get { return underlyingResultsPublisher } + set(value) { underlyingResultsPublisher = value } + } + var underlyingResultsPublisher: CurrentValuePublisher<[RoomDirectorySearchResult], Never>! - var loadDraftUnderlyingCallsCount = 0 - var loadDraftCallsCount: Int { + //MARK: - search + + var searchQueryUnderlyingCallsCount = 0 + var searchQueryCallsCount: Int { get { if Thread.isMainThread { - return loadDraftUnderlyingCallsCount + return searchQueryUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = loadDraftUnderlyingCallsCount + returnValue = searchQueryUnderlyingCallsCount } return returnValue! @@ -11189,27 +11724,29 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - loadDraftUnderlyingCallsCount = newValue + searchQueryUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - loadDraftUnderlyingCallsCount = newValue + searchQueryUnderlyingCallsCount = newValue } } } } - var loadDraftCalled: Bool { - return loadDraftCallsCount > 0 + var searchQueryCalled: Bool { + return searchQueryCallsCount > 0 } + var searchQueryReceivedQuery: String? + var searchQueryReceivedInvocations: [String?] = [] - var loadDraftUnderlyingReturnValue: Result! - var loadDraftReturnValue: Result! { + var searchQueryUnderlyingReturnValue: Result! + var searchQueryReturnValue: Result! { get { if Thread.isMainThread { - return loadDraftUnderlyingReturnValue + return searchQueryUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = loadDraftUnderlyingReturnValue + returnValue = searchQueryUnderlyingReturnValue } return returnValue! @@ -11217,35 +11754,39 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - loadDraftUnderlyingReturnValue = newValue + searchQueryUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - loadDraftUnderlyingReturnValue = newValue + searchQueryUnderlyingReturnValue = newValue } } } } - var loadDraftClosure: (() async -> Result)? + var searchQueryClosure: ((String?) async -> Result)? - func loadDraft() async -> Result { - loadDraftCallsCount += 1 - if let loadDraftClosure = loadDraftClosure { - return await loadDraftClosure() + func search(query: String?) async -> Result { + searchQueryCallsCount += 1 + searchQueryReceivedQuery = query + DispatchQueue.main.async { + self.searchQueryReceivedInvocations.append(query) + } + if let searchQueryClosure = searchQueryClosure { + return await searchQueryClosure(query) } else { - return loadDraftReturnValue + return searchQueryReturnValue } } - //MARK: - clearDraft + //MARK: - nextPage - var clearDraftUnderlyingCallsCount = 0 - var clearDraftCallsCount: Int { + var nextPageUnderlyingCallsCount = 0 + var nextPageCallsCount: Int { get { if Thread.isMainThread { - return clearDraftUnderlyingCallsCount + return nextPageUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = clearDraftUnderlyingCallsCount + returnValue = nextPageUnderlyingCallsCount } return returnValue! @@ -11253,27 +11794,27 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - clearDraftUnderlyingCallsCount = newValue + nextPageUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - clearDraftUnderlyingCallsCount = newValue + nextPageUnderlyingCallsCount = newValue } } } } - var clearDraftCalled: Bool { - return clearDraftCallsCount > 0 + var nextPageCalled: Bool { + return nextPageCallsCount > 0 } - var clearDraftUnderlyingReturnValue: Result! - var clearDraftReturnValue: Result! { + var nextPageUnderlyingReturnValue: Result! + var nextPageReturnValue: Result! { get { if Thread.isMainThread { - return clearDraftUnderlyingReturnValue + return nextPageUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = clearDraftUnderlyingReturnValue + returnValue = nextPageUnderlyingReturnValue } return returnValue! @@ -11281,25 +11822,115 @@ class RoomProxyMock: RoomProxyProtocol { } set { if Thread.isMainThread { - clearDraftUnderlyingReturnValue = newValue + nextPageUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - clearDraftUnderlyingReturnValue = newValue + nextPageUnderlyingReturnValue = newValue } } } } - var clearDraftClosure: (() async -> Result)? + var nextPageClosure: (() async -> Result)? - func clearDraft() async -> Result { - clearDraftCallsCount += 1 - if let clearDraftClosure = clearDraftClosure { - return await clearDraftClosure() + func nextPage() async -> Result { + nextPageCallsCount += 1 + if let nextPageClosure = nextPageClosure { + return await nextPageClosure() } else { - return clearDraftReturnValue + return nextPageReturnValue } } } +class RoomMemberProxyMock: RoomMemberProxyProtocol { + var userID: String { + get { return underlyingUserID } + set(value) { underlyingUserID = value } + } + var underlyingUserID: String! + var displayName: String? + var avatarURL: URL? + var membership: MembershipState { + get { return underlyingMembership } + set(value) { underlyingMembership = value } + } + var underlyingMembership: MembershipState! + var isIgnored: Bool { + get { return underlyingIsIgnored } + set(value) { underlyingIsIgnored = value } + } + var underlyingIsIgnored: Bool! + var powerLevel: Int { + get { return underlyingPowerLevel } + set(value) { underlyingPowerLevel = value } + } + var underlyingPowerLevel: Int! + var role: RoomMemberRole { + get { return underlyingRole } + set(value) { underlyingRole = value } + } + var underlyingRole: RoomMemberRole! + +} +class RoomNotificationSettingsProxyMock: RoomNotificationSettingsProxyProtocol { + var mode: RoomNotificationModeProxy { + get { return underlyingMode } + set(value) { underlyingMode = value } + } + var underlyingMode: RoomNotificationModeProxy! + var isDefault: Bool { + get { return underlyingIsDefault } + set(value) { underlyingIsDefault = value } + } + var underlyingIsDefault: Bool! + +} +class RoomProxyMock: RoomProxyProtocol { + var id: String { + get { return underlyingId } + set(value) { underlyingId = value } + } + var underlyingId: String! + var canonicalAlias: String? + var ownUserID: String { + get { return underlyingOwnUserID } + set(value) { underlyingOwnUserID = value } + } + var underlyingOwnUserID: String! + var name: String? + var topic: String? + var avatar: RoomAvatar { + get { return underlyingAvatar } + set(value) { underlyingAvatar = value } + } + var underlyingAvatar: RoomAvatar! + var avatarURL: URL? + var isPublic: Bool { + get { return underlyingIsPublic } + set(value) { underlyingIsPublic = value } + } + var underlyingIsPublic: Bool! + var isDirect: Bool { + get { return underlyingIsDirect } + set(value) { underlyingIsDirect = value } + } + var underlyingIsDirect: Bool! + var isSpace: Bool { + get { return underlyingIsSpace } + set(value) { underlyingIsSpace = value } + } + var underlyingIsSpace: Bool! + var joinedMembersCount: Int { + get { return underlyingJoinedMembersCount } + set(value) { underlyingJoinedMembersCount = value } + } + var underlyingJoinedMembersCount: Int! + var activeMembersCount: Int { + get { return underlyingActiveMembersCount } + set(value) { underlyingActiveMembersCount = value } + } + var underlyingActiveMembersCount: Int! + +} class RoomSummaryProviderMock: RoomSummaryProviderProtocol { var roomListPublisher: CurrentValuePublisher<[RoomSummary], Never> { get { return underlyingRoomListPublisher } @@ -11467,8 +12098,8 @@ class RoomTimelineControllerFactoryMock: RoomTimelineControllerFactoryProtocol { var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryCalled: Bool { return buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryCallsCount > 0 } - var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReceivedArguments: (roomProxy: RoomProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol)? - var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReceivedInvocations: [(roomProxy: RoomProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol)] = [] + var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReceivedArguments: (roomProxy: JoinedRoomProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol)? + var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReceivedInvocations: [(roomProxy: JoinedRoomProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol)] = [] var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryUnderlyingReturnValue: RoomTimelineControllerProtocol! var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReturnValue: RoomTimelineControllerProtocol! { @@ -11494,9 +12125,9 @@ class RoomTimelineControllerFactoryMock: RoomTimelineControllerFactoryProtocol { } } } - var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryClosure: ((RoomProxyProtocol, String?, RoomTimelineItemFactoryProtocol) -> RoomTimelineControllerProtocol)? + var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryClosure: ((JoinedRoomProxyProtocol, String?, RoomTimelineItemFactoryProtocol) -> RoomTimelineControllerProtocol)? - func buildRoomTimelineController(roomProxy: RoomProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol) -> RoomTimelineControllerProtocol { + func buildRoomTimelineController(roomProxy: JoinedRoomProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol) -> RoomTimelineControllerProtocol { buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryCallsCount += 1 buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReceivedArguments = (roomProxy: roomProxy, initialFocussedEventID: initialFocussedEventID, timelineItemFactory: timelineItemFactory) DispatchQueue.main.async { @@ -11508,6 +12139,76 @@ class RoomTimelineControllerFactoryMock: RoomTimelineControllerFactoryProtocol { return buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReturnValue } } + //MARK: - buildRoomPinnedTimelineController + + var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryUnderlyingCallsCount = 0 + var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryCallsCount: Int { + get { + if Thread.isMainThread { + return buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryUnderlyingCallsCount = newValue + } + } + } + } + var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryCalled: Bool { + return buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryCallsCount > 0 + } + var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryReceivedArguments: (roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol)? + var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryReceivedInvocations: [(roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol)] = [] + + var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryUnderlyingReturnValue: RoomTimelineControllerProtocol? + var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryReturnValue: RoomTimelineControllerProtocol? { + get { + if Thread.isMainThread { + return buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryUnderlyingReturnValue + } else { + var returnValue: RoomTimelineControllerProtocol?? = nil + DispatchQueue.main.sync { + returnValue = buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryUnderlyingReturnValue = newValue + } + } + } + } + var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryClosure: ((JoinedRoomProxyProtocol, RoomTimelineItemFactoryProtocol) async -> RoomTimelineControllerProtocol?)? + + func buildRoomPinnedTimelineController(roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol) async -> RoomTimelineControllerProtocol? { + buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryCallsCount += 1 + buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryReceivedArguments = (roomProxy: roomProxy, timelineItemFactory: timelineItemFactory) + DispatchQueue.main.async { + self.buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryReceivedInvocations.append((roomProxy: roomProxy, timelineItemFactory: timelineItemFactory)) + } + if let buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryClosure = buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryClosure { + return await buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryClosure(roomProxy, timelineItemFactory) + } else { + return buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryReturnValue + } + } } class RoomTimelineProviderMock: RoomTimelineProviderProtocol { var updatePublisher: AnyPublisher<([TimelineItemProxy], PaginationState), Never> { @@ -11521,11 +12222,11 @@ class RoomTimelineProviderMock: RoomTimelineProviderProtocol { set(value) { underlyingPaginationState = value } } var underlyingPaginationState: PaginationState! - var isLive: Bool { - get { return underlyingIsLive } - set(value) { underlyingIsLive = value } + var kind: TimelineKind { + get { return underlyingKind } + set(value) { underlyingKind = value } } - var underlyingIsLive: Bool! + var underlyingKind: TimelineKind! var membershipChangePublisher: AnyPublisher { get { return underlyingMembershipChangePublisher } set(value) { underlyingMembershipChangePublisher = value } @@ -13443,8 +14144,8 @@ class TimelineProxyMock: TimelineProxyProtocol { var toggleReactionToCalled: Bool { return toggleReactionToCallsCount > 0 } - var toggleReactionToReceivedArguments: (reaction: String, eventID: String)? - var toggleReactionToReceivedInvocations: [(reaction: String, eventID: String)] = [] + var toggleReactionToReceivedArguments: (reaction: String, itemID: TimelineItemIdentifier)? + var toggleReactionToReceivedInvocations: [(reaction: String, itemID: TimelineItemIdentifier)] = [] var toggleReactionToUnderlyingReturnValue: Result! var toggleReactionToReturnValue: Result! { @@ -13470,16 +14171,16 @@ class TimelineProxyMock: TimelineProxyProtocol { } } } - var toggleReactionToClosure: ((String, String) async -> Result)? + var toggleReactionToClosure: ((String, TimelineItemIdentifier) async -> Result)? - func toggleReaction(_ reaction: String, to eventID: String) async -> Result { + func toggleReaction(_ reaction: String, to itemID: TimelineItemIdentifier) async -> Result { toggleReactionToCallsCount += 1 - toggleReactionToReceivedArguments = (reaction: reaction, eventID: eventID) + toggleReactionToReceivedArguments = (reaction: reaction, itemID: itemID) DispatchQueue.main.async { - self.toggleReactionToReceivedInvocations.append((reaction: reaction, eventID: eventID)) + self.toggleReactionToReceivedInvocations.append((reaction: reaction, itemID: itemID)) } if let toggleReactionToClosure = toggleReactionToClosure { - return await toggleReactionToClosure(reaction, eventID) + return await toggleReactionToClosure(reaction, itemID) } else { return toggleReactionToReturnValue } @@ -15213,8 +15914,8 @@ class VoiceMessageRecorderMock: VoiceMessageRecorderProtocol { var sendVoiceMessageInRoomAudioConverterCalled: Bool { return sendVoiceMessageInRoomAudioConverterCallsCount > 0 } - var sendVoiceMessageInRoomAudioConverterReceivedArguments: (roomProxy: RoomProxyProtocol, audioConverter: AudioConverterProtocol)? - var sendVoiceMessageInRoomAudioConverterReceivedInvocations: [(roomProxy: RoomProxyProtocol, audioConverter: AudioConverterProtocol)] = [] + var sendVoiceMessageInRoomAudioConverterReceivedArguments: (roomProxy: JoinedRoomProxyProtocol, audioConverter: AudioConverterProtocol)? + var sendVoiceMessageInRoomAudioConverterReceivedInvocations: [(roomProxy: JoinedRoomProxyProtocol, audioConverter: AudioConverterProtocol)] = [] var sendVoiceMessageInRoomAudioConverterUnderlyingReturnValue: Result! var sendVoiceMessageInRoomAudioConverterReturnValue: Result! { @@ -15240,9 +15941,9 @@ class VoiceMessageRecorderMock: VoiceMessageRecorderProtocol { } } } - var sendVoiceMessageInRoomAudioConverterClosure: ((RoomProxyProtocol, AudioConverterProtocol) async -> Result)? + var sendVoiceMessageInRoomAudioConverterClosure: ((JoinedRoomProxyProtocol, AudioConverterProtocol) async -> Result)? - func sendVoiceMessage(inRoom roomProxy: RoomProxyProtocol, audioConverter: AudioConverterProtocol) async -> Result { + func sendVoiceMessage(inRoom roomProxy: JoinedRoomProxyProtocol, audioConverter: AudioConverterProtocol) async -> Result { sendVoiceMessageInRoomAudioConverterCallsCount += 1 sendVoiceMessageInRoomAudioConverterReceivedArguments = (roomProxy: roomProxy, audioConverter: audioConverter) DispatchQueue.main.async { diff --git a/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift index 07464daaa7..152c0940c9 100644 --- a/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift @@ -207,6 +207,71 @@ open class ClientSDKMock: MatrixRustSDK.Client { } } + //MARK: - availableSlidingSyncVersions + + var availableSlidingSyncVersionsUnderlyingCallsCount = 0 + open var availableSlidingSyncVersionsCallsCount: Int { + get { + if Thread.isMainThread { + return availableSlidingSyncVersionsUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = availableSlidingSyncVersionsUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + availableSlidingSyncVersionsUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + availableSlidingSyncVersionsUnderlyingCallsCount = newValue + } + } + } + } + open var availableSlidingSyncVersionsCalled: Bool { + return availableSlidingSyncVersionsCallsCount > 0 + } + + var availableSlidingSyncVersionsUnderlyingReturnValue: [SlidingSyncVersion]! + open var availableSlidingSyncVersionsReturnValue: [SlidingSyncVersion]! { + get { + if Thread.isMainThread { + return availableSlidingSyncVersionsUnderlyingReturnValue + } else { + var returnValue: [SlidingSyncVersion]? = nil + DispatchQueue.main.sync { + returnValue = availableSlidingSyncVersionsUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + availableSlidingSyncVersionsUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + availableSlidingSyncVersionsUnderlyingReturnValue = newValue + } + } + } + } + open var availableSlidingSyncVersionsClosure: (() async -> [SlidingSyncVersion])? + + open override func availableSlidingSyncVersions() async -> [SlidingSyncVersion] { + availableSlidingSyncVersionsCallsCount += 1 + if let availableSlidingSyncVersionsClosure = availableSlidingSyncVersionsClosure { + return await availableSlidingSyncVersionsClosure() + } else { + return availableSlidingSyncVersionsReturnValue + } + } + //MARK: - avatarUrl open var avatarUrlThrowableError: Error? @@ -276,6 +341,81 @@ open class ClientSDKMock: MatrixRustSDK.Client { } } + //MARK: - awaitRoomRemoteEcho + + open var awaitRoomRemoteEchoRoomIdThrowableError: Error? + var awaitRoomRemoteEchoRoomIdUnderlyingCallsCount = 0 + open var awaitRoomRemoteEchoRoomIdCallsCount: Int { + get { + if Thread.isMainThread { + return awaitRoomRemoteEchoRoomIdUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = awaitRoomRemoteEchoRoomIdUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + awaitRoomRemoteEchoRoomIdUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + awaitRoomRemoteEchoRoomIdUnderlyingCallsCount = newValue + } + } + } + } + open var awaitRoomRemoteEchoRoomIdCalled: Bool { + return awaitRoomRemoteEchoRoomIdCallsCount > 0 + } + open var awaitRoomRemoteEchoRoomIdReceivedRoomId: String? + open var awaitRoomRemoteEchoRoomIdReceivedInvocations: [String] = [] + + var awaitRoomRemoteEchoRoomIdUnderlyingReturnValue: Room! + open var awaitRoomRemoteEchoRoomIdReturnValue: Room! { + get { + if Thread.isMainThread { + return awaitRoomRemoteEchoRoomIdUnderlyingReturnValue + } else { + var returnValue: Room? = nil + DispatchQueue.main.sync { + returnValue = awaitRoomRemoteEchoRoomIdUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + awaitRoomRemoteEchoRoomIdUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + awaitRoomRemoteEchoRoomIdUnderlyingReturnValue = newValue + } + } + } + } + open var awaitRoomRemoteEchoRoomIdClosure: ((String) async throws -> Room)? + + open override func awaitRoomRemoteEcho(roomId: String) async throws -> Room { + if let error = awaitRoomRemoteEchoRoomIdThrowableError { + throw error + } + awaitRoomRemoteEchoRoomIdCallsCount += 1 + awaitRoomRemoteEchoRoomIdReceivedRoomId = roomId + DispatchQueue.main.async { + self.awaitRoomRemoteEchoRoomIdReceivedInvocations.append(roomId) + } + if let awaitRoomRemoteEchoRoomIdClosure = awaitRoomRemoteEchoRoomIdClosure { + return try await awaitRoomRemoteEchoRoomIdClosure(roomId) + } else { + return awaitRoomRemoteEchoRoomIdReturnValue + } + } + //MARK: - cachedAvatarUrl open var cachedAvatarUrlThrowableError: Error? @@ -345,6 +485,71 @@ open class ClientSDKMock: MatrixRustSDK.Client { } } + //MARK: - canDeactivateAccount + + var canDeactivateAccountUnderlyingCallsCount = 0 + open var canDeactivateAccountCallsCount: Int { + get { + if Thread.isMainThread { + return canDeactivateAccountUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = canDeactivateAccountUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + canDeactivateAccountUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + canDeactivateAccountUnderlyingCallsCount = newValue + } + } + } + } + open var canDeactivateAccountCalled: Bool { + return canDeactivateAccountCallsCount > 0 + } + + var canDeactivateAccountUnderlyingReturnValue: Bool! + open var canDeactivateAccountReturnValue: Bool! { + get { + if Thread.isMainThread { + return canDeactivateAccountUnderlyingReturnValue + } else { + var returnValue: Bool? = nil + DispatchQueue.main.sync { + returnValue = canDeactivateAccountUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + canDeactivateAccountUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + canDeactivateAccountUnderlyingReturnValue = newValue + } + } + } + } + open var canDeactivateAccountClosure: (() -> Bool)? + + open override func canDeactivateAccount() -> Bool { + canDeactivateAccountCallsCount += 1 + if let canDeactivateAccountClosure = canDeactivateAccountClosure { + return canDeactivateAccountClosure() + } else { + return canDeactivateAccountReturnValue + } + } + //MARK: - createRoom open var createRoomRequestThrowableError: Error? @@ -420,6 +625,52 @@ open class ClientSDKMock: MatrixRustSDK.Client { } } + //MARK: - deactivateAccount + + open var deactivateAccountAuthDataEraseDataThrowableError: Error? + var deactivateAccountAuthDataEraseDataUnderlyingCallsCount = 0 + open var deactivateAccountAuthDataEraseDataCallsCount: Int { + get { + if Thread.isMainThread { + return deactivateAccountAuthDataEraseDataUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = deactivateAccountAuthDataEraseDataUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + deactivateAccountAuthDataEraseDataUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + deactivateAccountAuthDataEraseDataUnderlyingCallsCount = newValue + } + } + } + } + open var deactivateAccountAuthDataEraseDataCalled: Bool { + return deactivateAccountAuthDataEraseDataCallsCount > 0 + } + open var deactivateAccountAuthDataEraseDataReceivedArguments: (authData: AuthData?, eraseData: Bool)? + open var deactivateAccountAuthDataEraseDataReceivedInvocations: [(authData: AuthData?, eraseData: Bool)] = [] + open var deactivateAccountAuthDataEraseDataClosure: ((AuthData?, Bool) async throws -> Void)? + + open override func deactivateAccount(authData: AuthData?, eraseData: Bool) async throws { + if let error = deactivateAccountAuthDataEraseDataThrowableError { + throw error + } + deactivateAccountAuthDataEraseDataCallsCount += 1 + deactivateAccountAuthDataEraseDataReceivedArguments = (authData: authData, eraseData: eraseData) + DispatchQueue.main.async { + self.deactivateAccountAuthDataEraseDataReceivedInvocations.append((authData: authData, eraseData: eraseData)) + } + try await deactivateAccountAuthDataEraseDataClosure?(authData, eraseData) + } + //MARK: - deletePusher open var deletePusherIdentifiersThrowableError: Error? @@ -1955,6 +2206,52 @@ open class ClientSDKMock: MatrixRustSDK.Client { try await loginUsernamePasswordInitialDeviceNameDeviceIdClosure?(username, password, initialDeviceName, deviceId) } + //MARK: - loginWithEmail + + open var loginWithEmailEmailPasswordInitialDeviceNameDeviceIdThrowableError: Error? + var loginWithEmailEmailPasswordInitialDeviceNameDeviceIdUnderlyingCallsCount = 0 + open var loginWithEmailEmailPasswordInitialDeviceNameDeviceIdCallsCount: Int { + get { + if Thread.isMainThread { + return loginWithEmailEmailPasswordInitialDeviceNameDeviceIdUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = loginWithEmailEmailPasswordInitialDeviceNameDeviceIdUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + loginWithEmailEmailPasswordInitialDeviceNameDeviceIdUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + loginWithEmailEmailPasswordInitialDeviceNameDeviceIdUnderlyingCallsCount = newValue + } + } + } + } + open var loginWithEmailEmailPasswordInitialDeviceNameDeviceIdCalled: Bool { + return loginWithEmailEmailPasswordInitialDeviceNameDeviceIdCallsCount > 0 + } + open var loginWithEmailEmailPasswordInitialDeviceNameDeviceIdReceivedArguments: (email: String, password: String, initialDeviceName: String?, deviceId: String?)? + open var loginWithEmailEmailPasswordInitialDeviceNameDeviceIdReceivedInvocations: [(email: String, password: String, initialDeviceName: String?, deviceId: String?)] = [] + open var loginWithEmailEmailPasswordInitialDeviceNameDeviceIdClosure: ((String, String, String?, String?) async throws -> Void)? + + open override func loginWithEmail(email: String, password: String, initialDeviceName: String?, deviceId: String?) async throws { + if let error = loginWithEmailEmailPasswordInitialDeviceNameDeviceIdThrowableError { + throw error + } + loginWithEmailEmailPasswordInitialDeviceNameDeviceIdCallsCount += 1 + loginWithEmailEmailPasswordInitialDeviceNameDeviceIdReceivedArguments = (email: email, password: password, initialDeviceName: initialDeviceName, deviceId: deviceId) + DispatchQueue.main.async { + self.loginWithEmailEmailPasswordInitialDeviceNameDeviceIdReceivedInvocations.append((email: email, password: password, initialDeviceName: initialDeviceName, deviceId: deviceId)) + } + try await loginWithEmailEmailPasswordInitialDeviceNameDeviceIdClosure?(email, password, initialDeviceName, deviceId) + } + //MARK: - loginWithOidcCallback open var loginWithOidcCallbackAuthorizationDataCallbackUrlThrowableError: Error? @@ -2551,6 +2848,71 @@ open class ClientSDKMock: MatrixRustSDK.Client { } } + //MARK: - server + + var serverUnderlyingCallsCount = 0 + open var serverCallsCount: Int { + get { + if Thread.isMainThread { + return serverUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = serverUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + serverUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + serverUnderlyingCallsCount = newValue + } + } + } + } + open var serverCalled: Bool { + return serverCallsCount > 0 + } + + var serverUnderlyingReturnValue: String? + open var serverReturnValue: String? { + get { + if Thread.isMainThread { + return serverUnderlyingReturnValue + } else { + var returnValue: String?? = nil + DispatchQueue.main.sync { + returnValue = serverUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + serverUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + serverUnderlyingReturnValue = newValue + } + } + } + } + open var serverClosure: (() -> String?)? + + open override func server() -> String? { + serverCallsCount += 1 + if let serverClosure = serverClosure { + return serverClosure() + } else { + return serverReturnValue + } + } + //MARK: - session open var sessionThrowableError: Error? @@ -2829,6 +3191,71 @@ open class ClientSDKMock: MatrixRustSDK.Client { try await setPusherIdentifiersKindAppDisplayNameDeviceDisplayNameProfileTagLangClosure?(identifiers, kind, appDisplayName, deviceDisplayName, profileTag, lang) } + //MARK: - slidingSyncVersion + + var slidingSyncVersionUnderlyingCallsCount = 0 + open var slidingSyncVersionCallsCount: Int { + get { + if Thread.isMainThread { + return slidingSyncVersionUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = slidingSyncVersionUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + slidingSyncVersionUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + slidingSyncVersionUnderlyingCallsCount = newValue + } + } + } + } + open var slidingSyncVersionCalled: Bool { + return slidingSyncVersionCallsCount > 0 + } + + var slidingSyncVersionUnderlyingReturnValue: SlidingSyncVersion! + open var slidingSyncVersionReturnValue: SlidingSyncVersion! { + get { + if Thread.isMainThread { + return slidingSyncVersionUnderlyingReturnValue + } else { + var returnValue: SlidingSyncVersion? = nil + DispatchQueue.main.sync { + returnValue = slidingSyncVersionUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + slidingSyncVersionUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + slidingSyncVersionUnderlyingReturnValue = newValue + } + } + } + } + open var slidingSyncVersionClosure: (() -> SlidingSyncVersion)? + + open override func slidingSyncVersion() -> SlidingSyncVersion { + slidingSyncVersionCallsCount += 1 + if let slidingSyncVersionClosure = slidingSyncVersionClosure { + return slidingSyncVersionClosure() + } else { + return slidingSyncVersionReturnValue + } + } + //MARK: - startSsoLogin open var startSsoLoginRedirectUrlIdpIdThrowableError: Error? @@ -4526,17 +4953,17 @@ open class ClientBuilderSDKMock: MatrixRustSDK.ClientBuilder { } } - //MARK: - requiresSlidingSync + //MARK: - roomKeyRecipientStrategy - var requiresSlidingSyncUnderlyingCallsCount = 0 - open var requiresSlidingSyncCallsCount: Int { + var roomKeyRecipientStrategyStrategyUnderlyingCallsCount = 0 + open var roomKeyRecipientStrategyStrategyCallsCount: Int { get { if Thread.isMainThread { - return requiresSlidingSyncUnderlyingCallsCount + return roomKeyRecipientStrategyStrategyUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = requiresSlidingSyncUnderlyingCallsCount + returnValue = roomKeyRecipientStrategyStrategyUnderlyingCallsCount } return returnValue! @@ -4544,27 +4971,29 @@ open class ClientBuilderSDKMock: MatrixRustSDK.ClientBuilder { } set { if Thread.isMainThread { - requiresSlidingSyncUnderlyingCallsCount = newValue + roomKeyRecipientStrategyStrategyUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - requiresSlidingSyncUnderlyingCallsCount = newValue + roomKeyRecipientStrategyStrategyUnderlyingCallsCount = newValue } } } } - open var requiresSlidingSyncCalled: Bool { - return requiresSlidingSyncCallsCount > 0 + open var roomKeyRecipientStrategyStrategyCalled: Bool { + return roomKeyRecipientStrategyStrategyCallsCount > 0 } + open var roomKeyRecipientStrategyStrategyReceivedStrategy: CollectStrategy? + open var roomKeyRecipientStrategyStrategyReceivedInvocations: [CollectStrategy] = [] - var requiresSlidingSyncUnderlyingReturnValue: ClientBuilder! - open var requiresSlidingSyncReturnValue: ClientBuilder! { + var roomKeyRecipientStrategyStrategyUnderlyingReturnValue: ClientBuilder! + open var roomKeyRecipientStrategyStrategyReturnValue: ClientBuilder! { get { if Thread.isMainThread { - return requiresSlidingSyncUnderlyingReturnValue + return roomKeyRecipientStrategyStrategyUnderlyingReturnValue } else { var returnValue: ClientBuilder? = nil DispatchQueue.main.sync { - returnValue = requiresSlidingSyncUnderlyingReturnValue + returnValue = roomKeyRecipientStrategyStrategyUnderlyingReturnValue } return returnValue! @@ -4572,22 +5001,26 @@ open class ClientBuilderSDKMock: MatrixRustSDK.ClientBuilder { } set { if Thread.isMainThread { - requiresSlidingSyncUnderlyingReturnValue = newValue + roomKeyRecipientStrategyStrategyUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - requiresSlidingSyncUnderlyingReturnValue = newValue + roomKeyRecipientStrategyStrategyUnderlyingReturnValue = newValue } } } } - open var requiresSlidingSyncClosure: (() -> ClientBuilder)? + open var roomKeyRecipientStrategyStrategyClosure: ((CollectStrategy) -> ClientBuilder)? - open override func requiresSlidingSync() -> ClientBuilder { - requiresSlidingSyncCallsCount += 1 - if let requiresSlidingSyncClosure = requiresSlidingSyncClosure { - return requiresSlidingSyncClosure() + open override func roomKeyRecipientStrategy(strategy: CollectStrategy) -> ClientBuilder { + roomKeyRecipientStrategyStrategyCallsCount += 1 + roomKeyRecipientStrategyStrategyReceivedStrategy = strategy + DispatchQueue.main.async { + self.roomKeyRecipientStrategyStrategyReceivedInvocations.append(strategy) + } + if let roomKeyRecipientStrategyStrategyClosure = roomKeyRecipientStrategyStrategyClosure { + return roomKeyRecipientStrategyStrategyClosure(strategy) } else { - return requiresSlidingSyncReturnValue + return roomKeyRecipientStrategyStrategyReturnValue } } @@ -4733,17 +5166,17 @@ open class ClientBuilderSDKMock: MatrixRustSDK.ClientBuilder { } } - //MARK: - sessionPath + //MARK: - sessionPaths - var sessionPathPathUnderlyingCallsCount = 0 - open var sessionPathPathCallsCount: Int { + var sessionPathsDataPathCachePathUnderlyingCallsCount = 0 + open var sessionPathsDataPathCachePathCallsCount: Int { get { if Thread.isMainThread { - return sessionPathPathUnderlyingCallsCount + return sessionPathsDataPathCachePathUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = sessionPathPathUnderlyingCallsCount + returnValue = sessionPathsDataPathCachePathUnderlyingCallsCount } return returnValue! @@ -4751,29 +5184,29 @@ open class ClientBuilderSDKMock: MatrixRustSDK.ClientBuilder { } set { if Thread.isMainThread { - sessionPathPathUnderlyingCallsCount = newValue + sessionPathsDataPathCachePathUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - sessionPathPathUnderlyingCallsCount = newValue + sessionPathsDataPathCachePathUnderlyingCallsCount = newValue } } } } - open var sessionPathPathCalled: Bool { - return sessionPathPathCallsCount > 0 + open var sessionPathsDataPathCachePathCalled: Bool { + return sessionPathsDataPathCachePathCallsCount > 0 } - open var sessionPathPathReceivedPath: String? - open var sessionPathPathReceivedInvocations: [String] = [] + open var sessionPathsDataPathCachePathReceivedArguments: (dataPath: String, cachePath: String)? + open var sessionPathsDataPathCachePathReceivedInvocations: [(dataPath: String, cachePath: String)] = [] - var sessionPathPathUnderlyingReturnValue: ClientBuilder! - open var sessionPathPathReturnValue: ClientBuilder! { + var sessionPathsDataPathCachePathUnderlyingReturnValue: ClientBuilder! + open var sessionPathsDataPathCachePathReturnValue: ClientBuilder! { get { if Thread.isMainThread { - return sessionPathPathUnderlyingReturnValue + return sessionPathsDataPathCachePathUnderlyingReturnValue } else { var returnValue: ClientBuilder? = nil DispatchQueue.main.sync { - returnValue = sessionPathPathUnderlyingReturnValue + returnValue = sessionPathsDataPathCachePathUnderlyingReturnValue } return returnValue! @@ -4781,26 +5214,26 @@ open class ClientBuilderSDKMock: MatrixRustSDK.ClientBuilder { } set { if Thread.isMainThread { - sessionPathPathUnderlyingReturnValue = newValue + sessionPathsDataPathCachePathUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - sessionPathPathUnderlyingReturnValue = newValue + sessionPathsDataPathCachePathUnderlyingReturnValue = newValue } } } } - open var sessionPathPathClosure: ((String) -> ClientBuilder)? + open var sessionPathsDataPathCachePathClosure: ((String, String) -> ClientBuilder)? - open override func sessionPath(path: String) -> ClientBuilder { - sessionPathPathCallsCount += 1 - sessionPathPathReceivedPath = path + open override func sessionPaths(dataPath: String, cachePath: String) -> ClientBuilder { + sessionPathsDataPathCachePathCallsCount += 1 + sessionPathsDataPathCachePathReceivedArguments = (dataPath: dataPath, cachePath: cachePath) DispatchQueue.main.async { - self.sessionPathPathReceivedInvocations.append(path) + self.sessionPathsDataPathCachePathReceivedInvocations.append((dataPath: dataPath, cachePath: cachePath)) } - if let sessionPathPathClosure = sessionPathPathClosure { - return sessionPathPathClosure(path) + if let sessionPathsDataPathCachePathClosure = sessionPathsDataPathCachePathClosure { + return sessionPathsDataPathCachePathClosure(dataPath, cachePath) } else { - return sessionPathPathReturnValue + return sessionPathsDataPathCachePathReturnValue } } @@ -4875,88 +5308,17 @@ open class ClientBuilderSDKMock: MatrixRustSDK.ClientBuilder { } } - //MARK: - simplifiedSlidingSync - - var simplifiedSlidingSyncEnableUnderlyingCallsCount = 0 - open var simplifiedSlidingSyncEnableCallsCount: Int { - get { - if Thread.isMainThread { - return simplifiedSlidingSyncEnableUnderlyingCallsCount - } else { - var returnValue: Int? = nil - DispatchQueue.main.sync { - returnValue = simplifiedSlidingSyncEnableUnderlyingCallsCount - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - simplifiedSlidingSyncEnableUnderlyingCallsCount = newValue - } else { - DispatchQueue.main.sync { - simplifiedSlidingSyncEnableUnderlyingCallsCount = newValue - } - } - } - } - open var simplifiedSlidingSyncEnableCalled: Bool { - return simplifiedSlidingSyncEnableCallsCount > 0 - } - open var simplifiedSlidingSyncEnableReceivedEnable: Bool? - open var simplifiedSlidingSyncEnableReceivedInvocations: [Bool] = [] - - var simplifiedSlidingSyncEnableUnderlyingReturnValue: ClientBuilder! - open var simplifiedSlidingSyncEnableReturnValue: ClientBuilder! { - get { - if Thread.isMainThread { - return simplifiedSlidingSyncEnableUnderlyingReturnValue - } else { - var returnValue: ClientBuilder? = nil - DispatchQueue.main.sync { - returnValue = simplifiedSlidingSyncEnableUnderlyingReturnValue - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - simplifiedSlidingSyncEnableUnderlyingReturnValue = newValue - } else { - DispatchQueue.main.sync { - simplifiedSlidingSyncEnableUnderlyingReturnValue = newValue - } - } - } - } - open var simplifiedSlidingSyncEnableClosure: ((Bool) -> ClientBuilder)? - - open override func simplifiedSlidingSync(enable: Bool) -> ClientBuilder { - simplifiedSlidingSyncEnableCallsCount += 1 - simplifiedSlidingSyncEnableReceivedEnable = enable - DispatchQueue.main.async { - self.simplifiedSlidingSyncEnableReceivedInvocations.append(enable) - } - if let simplifiedSlidingSyncEnableClosure = simplifiedSlidingSyncEnableClosure { - return simplifiedSlidingSyncEnableClosure(enable) - } else { - return simplifiedSlidingSyncEnableReturnValue - } - } - - //MARK: - slidingSyncProxy + //MARK: - slidingSyncVersionBuilder - var slidingSyncProxySlidingSyncProxyUnderlyingCallsCount = 0 - open var slidingSyncProxySlidingSyncProxyCallsCount: Int { + var slidingSyncVersionBuilderVersionBuilderUnderlyingCallsCount = 0 + open var slidingSyncVersionBuilderVersionBuilderCallsCount: Int { get { if Thread.isMainThread { - return slidingSyncProxySlidingSyncProxyUnderlyingCallsCount + return slidingSyncVersionBuilderVersionBuilderUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = slidingSyncProxySlidingSyncProxyUnderlyingCallsCount + returnValue = slidingSyncVersionBuilderVersionBuilderUnderlyingCallsCount } return returnValue! @@ -4964,29 +5326,29 @@ open class ClientBuilderSDKMock: MatrixRustSDK.ClientBuilder { } set { if Thread.isMainThread { - slidingSyncProxySlidingSyncProxyUnderlyingCallsCount = newValue + slidingSyncVersionBuilderVersionBuilderUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - slidingSyncProxySlidingSyncProxyUnderlyingCallsCount = newValue + slidingSyncVersionBuilderVersionBuilderUnderlyingCallsCount = newValue } } } } - open var slidingSyncProxySlidingSyncProxyCalled: Bool { - return slidingSyncProxySlidingSyncProxyCallsCount > 0 + open var slidingSyncVersionBuilderVersionBuilderCalled: Bool { + return slidingSyncVersionBuilderVersionBuilderCallsCount > 0 } - open var slidingSyncProxySlidingSyncProxyReceivedSlidingSyncProxy: String? - open var slidingSyncProxySlidingSyncProxyReceivedInvocations: [String?] = [] + open var slidingSyncVersionBuilderVersionBuilderReceivedVersionBuilder: SlidingSyncVersionBuilder? + open var slidingSyncVersionBuilderVersionBuilderReceivedInvocations: [SlidingSyncVersionBuilder] = [] - var slidingSyncProxySlidingSyncProxyUnderlyingReturnValue: ClientBuilder! - open var slidingSyncProxySlidingSyncProxyReturnValue: ClientBuilder! { + var slidingSyncVersionBuilderVersionBuilderUnderlyingReturnValue: ClientBuilder! + open var slidingSyncVersionBuilderVersionBuilderReturnValue: ClientBuilder! { get { if Thread.isMainThread { - return slidingSyncProxySlidingSyncProxyUnderlyingReturnValue + return slidingSyncVersionBuilderVersionBuilderUnderlyingReturnValue } else { var returnValue: ClientBuilder? = nil DispatchQueue.main.sync { - returnValue = slidingSyncProxySlidingSyncProxyUnderlyingReturnValue + returnValue = slidingSyncVersionBuilderVersionBuilderUnderlyingReturnValue } return returnValue! @@ -4994,26 +5356,26 @@ open class ClientBuilderSDKMock: MatrixRustSDK.ClientBuilder { } set { if Thread.isMainThread { - slidingSyncProxySlidingSyncProxyUnderlyingReturnValue = newValue + slidingSyncVersionBuilderVersionBuilderUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - slidingSyncProxySlidingSyncProxyUnderlyingReturnValue = newValue + slidingSyncVersionBuilderVersionBuilderUnderlyingReturnValue = newValue } } } } - open var slidingSyncProxySlidingSyncProxyClosure: ((String?) -> ClientBuilder)? + open var slidingSyncVersionBuilderVersionBuilderClosure: ((SlidingSyncVersionBuilder) -> ClientBuilder)? - open override func slidingSyncProxy(slidingSyncProxy: String?) -> ClientBuilder { - slidingSyncProxySlidingSyncProxyCallsCount += 1 - slidingSyncProxySlidingSyncProxyReceivedSlidingSyncProxy = slidingSyncProxy + open override func slidingSyncVersionBuilder(versionBuilder: SlidingSyncVersionBuilder) -> ClientBuilder { + slidingSyncVersionBuilderVersionBuilderCallsCount += 1 + slidingSyncVersionBuilderVersionBuilderReceivedVersionBuilder = versionBuilder DispatchQueue.main.async { - self.slidingSyncProxySlidingSyncProxyReceivedInvocations.append(slidingSyncProxy) + self.slidingSyncVersionBuilderVersionBuilderReceivedInvocations.append(versionBuilder) } - if let slidingSyncProxySlidingSyncProxyClosure = slidingSyncProxySlidingSyncProxyClosure { - return slidingSyncProxySlidingSyncProxyClosure(slidingSyncProxy) + if let slidingSyncVersionBuilderVersionBuilderClosure = slidingSyncVersionBuilderVersionBuilderClosure { + return slidingSyncVersionBuilderVersionBuilderClosure(versionBuilder) } else { - return slidingSyncProxySlidingSyncProxyReturnValue + return slidingSyncVersionBuilderVersionBuilderReturnValue } } @@ -7475,17 +7837,17 @@ open class HomeserverLoginDetailsSDKMock: MatrixRustSDK.HomeserverLoginDetails { fileprivate var pointer: UnsafeMutableRawPointer! - //MARK: - slidingSyncProxy + //MARK: - slidingSyncVersion - var slidingSyncProxyUnderlyingCallsCount = 0 - open var slidingSyncProxyCallsCount: Int { + var slidingSyncVersionUnderlyingCallsCount = 0 + open var slidingSyncVersionCallsCount: Int { get { if Thread.isMainThread { - return slidingSyncProxyUnderlyingCallsCount + return slidingSyncVersionUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = slidingSyncProxyUnderlyingCallsCount + returnValue = slidingSyncVersionUnderlyingCallsCount } return returnValue! @@ -7493,27 +7855,27 @@ open class HomeserverLoginDetailsSDKMock: MatrixRustSDK.HomeserverLoginDetails { } set { if Thread.isMainThread { - slidingSyncProxyUnderlyingCallsCount = newValue + slidingSyncVersionUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - slidingSyncProxyUnderlyingCallsCount = newValue + slidingSyncVersionUnderlyingCallsCount = newValue } } } } - open var slidingSyncProxyCalled: Bool { - return slidingSyncProxyCallsCount > 0 + open var slidingSyncVersionCalled: Bool { + return slidingSyncVersionCallsCount > 0 } - var slidingSyncProxyUnderlyingReturnValue: String? - open var slidingSyncProxyReturnValue: String? { + var slidingSyncVersionUnderlyingReturnValue: SlidingSyncVersion! + open var slidingSyncVersionReturnValue: SlidingSyncVersion! { get { if Thread.isMainThread { - return slidingSyncProxyUnderlyingReturnValue + return slidingSyncVersionUnderlyingReturnValue } else { - var returnValue: String?? = nil + var returnValue: SlidingSyncVersion? = nil DispatchQueue.main.sync { - returnValue = slidingSyncProxyUnderlyingReturnValue + returnValue = slidingSyncVersionUnderlyingReturnValue } return returnValue! @@ -7521,22 +7883,22 @@ open class HomeserverLoginDetailsSDKMock: MatrixRustSDK.HomeserverLoginDetails { } set { if Thread.isMainThread { - slidingSyncProxyUnderlyingReturnValue = newValue + slidingSyncVersionUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - slidingSyncProxyUnderlyingReturnValue = newValue + slidingSyncVersionUnderlyingReturnValue = newValue } } } } - open var slidingSyncProxyClosure: (() -> String?)? + open var slidingSyncVersionClosure: (() -> SlidingSyncVersion)? - open override func slidingSyncProxy() -> String? { - slidingSyncProxyCallsCount += 1 - if let slidingSyncProxyClosure = slidingSyncProxyClosure { - return slidingSyncProxyClosure() + open override func slidingSyncVersion() -> SlidingSyncVersion { + slidingSyncVersionCallsCount += 1 + if let slidingSyncVersionClosure = slidingSyncVersionClosure { + return slidingSyncVersionClosure() } else { - return slidingSyncProxyReturnValue + return slidingSyncVersionReturnValue } } @@ -7811,6 +8173,42 @@ open class IdentityResetHandleSDKMock: MatrixRustSDK.IdentityResetHandle { } } + //MARK: - cancel + + var cancelUnderlyingCallsCount = 0 + open var cancelCallsCount: Int { + get { + if Thread.isMainThread { + return cancelUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = cancelUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + cancelUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + cancelUnderlyingCallsCount = newValue + } + } + } + } + open var cancelCalled: Bool { + return cancelCallsCount > 0 + } + open var cancelClosure: (() async -> Void)? + + open override func cancel() async { + cancelCallsCount += 1 + await cancelClosure?() + } + //MARK: - reset open var resetAuthThrowableError: Error? @@ -11060,42 +11458,6 @@ open class RoomSDKMock: MatrixRustSDK.Room { try await clearComposerDraftClosure?() } - //MARK: - clearPinnedEventsCache - - var clearPinnedEventsCacheUnderlyingCallsCount = 0 - open var clearPinnedEventsCacheCallsCount: Int { - get { - if Thread.isMainThread { - return clearPinnedEventsCacheUnderlyingCallsCount - } else { - var returnValue: Int? = nil - DispatchQueue.main.sync { - returnValue = clearPinnedEventsCacheUnderlyingCallsCount - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - clearPinnedEventsCacheUnderlyingCallsCount = newValue - } else { - DispatchQueue.main.sync { - clearPinnedEventsCacheUnderlyingCallsCount = newValue - } - } - } - } - open var clearPinnedEventsCacheCalled: Bool { - return clearPinnedEventsCacheCallsCount > 0 - } - open var clearPinnedEventsCacheClosure: (() async -> Void)? - - open override func clearPinnedEventsCache() async { - clearPinnedEventsCacheCallsCount += 1 - await clearPinnedEventsCacheClosure?() - } - //MARK: - discardRoomKey open var discardRoomKeyThrowableError: Error? @@ -11537,20 +11899,66 @@ open class RoomSDKMock: MatrixRustSDK.Room { idUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - idUnderlyingReturnValue = newValue + idUnderlyingReturnValue = newValue + } + } + } + } + open var idClosure: (() -> String)? + + open override func id() -> String { + idCallsCount += 1 + if let idClosure = idClosure { + return idClosure() + } else { + return idReturnValue + } + } + + //MARK: - ignoreDeviceTrustAndResend + + open var ignoreDeviceTrustAndResendDevicesTransactionIdThrowableError: Error? + var ignoreDeviceTrustAndResendDevicesTransactionIdUnderlyingCallsCount = 0 + open var ignoreDeviceTrustAndResendDevicesTransactionIdCallsCount: Int { + get { + if Thread.isMainThread { + return ignoreDeviceTrustAndResendDevicesTransactionIdUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = ignoreDeviceTrustAndResendDevicesTransactionIdUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + ignoreDeviceTrustAndResendDevicesTransactionIdUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + ignoreDeviceTrustAndResendDevicesTransactionIdUnderlyingCallsCount = newValue } } } } - open var idClosure: (() -> String)? + open var ignoreDeviceTrustAndResendDevicesTransactionIdCalled: Bool { + return ignoreDeviceTrustAndResendDevicesTransactionIdCallsCount > 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 override func id() -> String { - idCallsCount += 1 - if let idClosure = idClosure { - return idClosure() - } else { - return idReturnValue + open override func ignoreDeviceTrustAndResend(devices: [String: [String]], transactionId: String) async throws { + if let error = ignoreDeviceTrustAndResendDevicesTransactionIdThrowableError { + throw error + } + ignoreDeviceTrustAndResendDevicesTransactionIdCallsCount += 1 + ignoreDeviceTrustAndResendDevicesTransactionIdReceivedArguments = (devices: devices, transactionId: transactionId) + DispatchQueue.main.async { + self.ignoreDeviceTrustAndResendDevicesTransactionIdReceivedInvocations.append((devices: devices, transactionId: transactionId)) } + try await ignoreDeviceTrustAndResendDevicesTransactionIdClosure?(devices, transactionId) } //MARK: - ignoreUser @@ -13114,16 +13522,16 @@ open class RoomSDKMock: MatrixRustSDK.Room { //MARK: - pinnedEventsTimeline - open var pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadThrowableError: Error? - var pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadUnderlyingCallsCount = 0 - open var pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadCallsCount: Int { + open var pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsThrowableError: Error? + var pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsUnderlyingCallsCount = 0 + open var pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsCallsCount: Int { get { if Thread.isMainThread { - return pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadUnderlyingCallsCount + return pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadUnderlyingCallsCount + returnValue = pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsUnderlyingCallsCount } return returnValue! @@ -13131,29 +13539,29 @@ open class RoomSDKMock: MatrixRustSDK.Room { } set { if Thread.isMainThread { - pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadUnderlyingCallsCount = newValue + pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadUnderlyingCallsCount = newValue + pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsUnderlyingCallsCount = newValue } } } } - open var pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadCalled: Bool { - return pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadCallsCount > 0 + open var pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsCalled: Bool { + return pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsCallsCount > 0 } - open var pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadReceivedArguments: (internalIdPrefix: String?, maxEventsToLoad: UInt16)? - open var pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadReceivedInvocations: [(internalIdPrefix: String?, maxEventsToLoad: UInt16)] = [] + open var pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsReceivedArguments: (internalIdPrefix: String?, maxEventsToLoad: UInt16, maxConcurrentRequests: UInt16)? + open var pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsReceivedInvocations: [(internalIdPrefix: String?, maxEventsToLoad: UInt16, maxConcurrentRequests: UInt16)] = [] - var pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadUnderlyingReturnValue: Timeline! - open var pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadReturnValue: Timeline! { + var pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsUnderlyingReturnValue: Timeline! + open var pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsReturnValue: Timeline! { get { if Thread.isMainThread { - return pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadUnderlyingReturnValue + return pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsUnderlyingReturnValue } else { var returnValue: Timeline? = nil DispatchQueue.main.sync { - returnValue = pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadUnderlyingReturnValue + returnValue = pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsUnderlyingReturnValue } return returnValue! @@ -13161,29 +13569,29 @@ open class RoomSDKMock: MatrixRustSDK.Room { } set { if Thread.isMainThread { - pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadUnderlyingReturnValue = newValue + pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadUnderlyingReturnValue = newValue + pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsUnderlyingReturnValue = newValue } } } } - open var pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadClosure: ((String?, UInt16) async throws -> Timeline)? + open var pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsClosure: ((String?, UInt16, UInt16) async throws -> Timeline)? - open override func pinnedEventsTimeline(internalIdPrefix: String?, maxEventsToLoad: UInt16) async throws -> Timeline { - if let error = pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadThrowableError { + open override func pinnedEventsTimeline(internalIdPrefix: String?, maxEventsToLoad: UInt16, maxConcurrentRequests: UInt16) async throws -> Timeline { + if let error = pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsThrowableError { throw error } - pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadCallsCount += 1 - pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadReceivedArguments = (internalIdPrefix: internalIdPrefix, maxEventsToLoad: maxEventsToLoad) + pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsCallsCount += 1 + pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsReceivedArguments = (internalIdPrefix: internalIdPrefix, maxEventsToLoad: maxEventsToLoad, maxConcurrentRequests: maxConcurrentRequests) DispatchQueue.main.async { - self.pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadReceivedInvocations.append((internalIdPrefix: internalIdPrefix, maxEventsToLoad: maxEventsToLoad)) + self.pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsReceivedInvocations.append((internalIdPrefix: internalIdPrefix, maxEventsToLoad: maxEventsToLoad, maxConcurrentRequests: maxConcurrentRequests)) } - if let pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadClosure = pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadClosure { - return try await pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadClosure(internalIdPrefix, maxEventsToLoad) + if let pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsClosure = pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsClosure { + return try await pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsClosure(internalIdPrefix, maxEventsToLoad, maxConcurrentRequests) } else { - return pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadReturnValue + return pinnedEventsTimelineInternalIdPrefixMaxEventsToLoadMaxConcurrentRequestsReturnValue } } @@ -14310,6 +14718,52 @@ 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? @@ -14493,6 +14947,52 @@ open class RoomSDKMock: MatrixRustSDK.Room { } try await uploadAvatarMimeTypeDataMediaInfoClosure?(mimeType, data, mediaInfo) } + + //MARK: - withdrawVerificationAndResend + + open var withdrawVerificationAndResendUserIdsTransactionIdThrowableError: Error? + var withdrawVerificationAndResendUserIdsTransactionIdUnderlyingCallsCount = 0 + open var withdrawVerificationAndResendUserIdsTransactionIdCallsCount: Int { + get { + if Thread.isMainThread { + return withdrawVerificationAndResendUserIdsTransactionIdUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = withdrawVerificationAndResendUserIdsTransactionIdUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + withdrawVerificationAndResendUserIdsTransactionIdUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + withdrawVerificationAndResendUserIdsTransactionIdUnderlyingCallsCount = newValue + } + } + } + } + open var withdrawVerificationAndResendUserIdsTransactionIdCalled: Bool { + return withdrawVerificationAndResendUserIdsTransactionIdCallsCount > 0 + } + open var withdrawVerificationAndResendUserIdsTransactionIdReceivedArguments: (userIds: [String], transactionId: String)? + open var withdrawVerificationAndResendUserIdsTransactionIdReceivedInvocations: [(userIds: [String], transactionId: String)] = [] + open var withdrawVerificationAndResendUserIdsTransactionIdClosure: (([String], String) async throws -> Void)? + + open override func withdrawVerificationAndResend(userIds: [String], transactionId: String) async throws { + if let error = withdrawVerificationAndResendUserIdsTransactionIdThrowableError { + throw error + } + withdrawVerificationAndResendUserIdsTransactionIdCallsCount += 1 + withdrawVerificationAndResendUserIdsTransactionIdReceivedArguments = (userIds: userIds, transactionId: transactionId) + DispatchQueue.main.async { + self.withdrawVerificationAndResendUserIdsTransactionIdReceivedInvocations.append((userIds: userIds, transactionId: transactionId)) + } + try await withdrawVerificationAndResendUserIdsTransactionIdClosure?(userIds, transactionId) + } } open class RoomDirectorySearchSDKMock: MatrixRustSDK.RoomDirectorySearch { init() { @@ -15784,6 +16284,75 @@ open class RoomListItemSDKMock: MatrixRustSDK.RoomListItem { try await initTimelineEventTypeFilterInternalIdPrefixClosure?(eventTypeFilter, internalIdPrefix) } + //MARK: - invitedRoom + + open var invitedRoomThrowableError: Error? + var invitedRoomUnderlyingCallsCount = 0 + open var invitedRoomCallsCount: Int { + get { + if Thread.isMainThread { + return invitedRoomUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = invitedRoomUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + invitedRoomUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + invitedRoomUnderlyingCallsCount = newValue + } + } + } + } + open var invitedRoomCalled: Bool { + return invitedRoomCallsCount > 0 + } + + var invitedRoomUnderlyingReturnValue: Room! + open var invitedRoomReturnValue: Room! { + get { + if Thread.isMainThread { + return invitedRoomUnderlyingReturnValue + } else { + var returnValue: Room? = nil + DispatchQueue.main.sync { + returnValue = invitedRoomUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + invitedRoomUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + invitedRoomUnderlyingReturnValue = newValue + } + } + } + } + open var invitedRoomClosure: (() throws -> Room)? + + open override func invitedRoom() throws -> Room { + if let error = invitedRoomThrowableError { + throw error + } + invitedRoomCallsCount += 1 + if let invitedRoomClosure = invitedRoomClosure { + return try invitedRoomClosure() + } else { + return invitedRoomReturnValue + } + } + //MARK: - isDirect var isDirectUnderlyingCallsCount = 0 @@ -16044,6 +16613,71 @@ open class RoomListItemSDKMock: MatrixRustSDK.RoomListItem { } } + //MARK: - membership + + var membershipUnderlyingCallsCount = 0 + open var membershipCallsCount: Int { + get { + if Thread.isMainThread { + return membershipUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = membershipUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + membershipUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + membershipUnderlyingCallsCount = newValue + } + } + } + } + open var membershipCalled: Bool { + return membershipCallsCount > 0 + } + + var membershipUnderlyingReturnValue: Membership! + open var membershipReturnValue: Membership! { + get { + if Thread.isMainThread { + return membershipUnderlyingReturnValue + } else { + var returnValue: Membership? = nil + DispatchQueue.main.sync { + returnValue = membershipUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + membershipUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + membershipUnderlyingReturnValue = newValue + } + } + } + } + open var membershipClosure: (() -> Membership)? + + open override func membership() -> Membership { + membershipCallsCount += 1 + if let membershipClosure = membershipClosure { + return membershipClosure() + } else { + return membershipReturnValue + } + } + //MARK: - roomInfo open var roomInfoThrowableError: Error? @@ -16366,6 +17000,25 @@ open class RoomListServiceSDKMock: MatrixRustSDK.RoomListService { } } } + open var subscribeToRoomsRoomIdsSettingsCalled: Bool { + return subscribeToRoomsRoomIdsSettingsCallsCount > 0 + } + open var subscribeToRoomsRoomIdsSettingsReceivedArguments: (roomIds: [String], settings: RoomSubscription?)? + open var subscribeToRoomsRoomIdsSettingsReceivedInvocations: [(roomIds: [String], settings: RoomSubscription?)] = [] + open var subscribeToRoomsRoomIdsSettingsClosure: (([String], RoomSubscription?) throws -> Void)? + + open override func subscribeToRooms(roomIds: [String], settings: RoomSubscription?) throws { + if let error = subscribeToRoomsRoomIdsSettingsThrowableError { + throw error + } + subscribeToRoomsRoomIdsSettingsCallsCount += 1 + subscribeToRoomsRoomIdsSettingsReceivedArguments = (roomIds: roomIds, settings: settings) + DispatchQueue.main.async { + self.subscribeToRoomsRoomIdsSettingsReceivedInvocations.append((roomIds: roomIds, settings: settings)) + } + try subscribeToRoomsRoomIdsSettingsClosure?(roomIds, settings) + } + //MARK: - syncIndicator var syncIndicatorDelayBeforeShowingInMsDelayBeforeHidingInMsListenerUnderlyingCallsCount = 0 @@ -18284,8 +18937,8 @@ open class TimelineSDKMock: MatrixRustSDK.Timeline { open var editItemNewContentCalled: Bool { return editItemNewContentCallsCount > 0 } - open var editItemNewContentReceivedArguments: (item: EventTimelineItem, newContent: RoomMessageEventContentWithoutRelation)? - open var editItemNewContentReceivedInvocations: [(item: EventTimelineItem, newContent: RoomMessageEventContentWithoutRelation)] = [] + open var editItemNewContentReceivedArguments: (item: EventTimelineItem, newContent: EditedContent)? + open var editItemNewContentReceivedInvocations: [(item: EventTimelineItem, newContent: EditedContent)] = [] var editItemNewContentUnderlyingReturnValue: Bool! open var editItemNewContentReturnValue: Bool! { @@ -18311,9 +18964,9 @@ open class TimelineSDKMock: MatrixRustSDK.Timeline { } } } - open var editItemNewContentClosure: ((EventTimelineItem, RoomMessageEventContentWithoutRelation) async throws -> Bool)? + open var editItemNewContentClosure: ((EventTimelineItem, EditedContent) async throws -> Bool)? - open override func edit(item: EventTimelineItem, newContent: RoomMessageEventContentWithoutRelation) async throws -> Bool { + open override func edit(item: EventTimelineItem, newContent: EditedContent) async throws -> Bool { if let error = editItemNewContentThrowableError { throw error } @@ -18329,52 +18982,6 @@ open class TimelineSDKMock: MatrixRustSDK.Timeline { } } - //MARK: - editPoll - - open var editPollQuestionAnswersMaxSelectionsPollKindEditItemThrowableError: Error? - var editPollQuestionAnswersMaxSelectionsPollKindEditItemUnderlyingCallsCount = 0 - open var editPollQuestionAnswersMaxSelectionsPollKindEditItemCallsCount: Int { - get { - if Thread.isMainThread { - return editPollQuestionAnswersMaxSelectionsPollKindEditItemUnderlyingCallsCount - } else { - var returnValue: Int? = nil - DispatchQueue.main.sync { - returnValue = editPollQuestionAnswersMaxSelectionsPollKindEditItemUnderlyingCallsCount - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - editPollQuestionAnswersMaxSelectionsPollKindEditItemUnderlyingCallsCount = newValue - } else { - DispatchQueue.main.sync { - editPollQuestionAnswersMaxSelectionsPollKindEditItemUnderlyingCallsCount = newValue - } - } - } - } - open var editPollQuestionAnswersMaxSelectionsPollKindEditItemCalled: Bool { - return editPollQuestionAnswersMaxSelectionsPollKindEditItemCallsCount > 0 - } - open var editPollQuestionAnswersMaxSelectionsPollKindEditItemReceivedArguments: (question: String, answers: [String], maxSelections: UInt8, pollKind: PollKind, editItem: EventTimelineItem)? - open var editPollQuestionAnswersMaxSelectionsPollKindEditItemReceivedInvocations: [(question: String, answers: [String], maxSelections: UInt8, pollKind: PollKind, editItem: EventTimelineItem)] = [] - open var editPollQuestionAnswersMaxSelectionsPollKindEditItemClosure: ((String, [String], UInt8, PollKind, EventTimelineItem) async throws -> Void)? - - open override func editPoll(question: String, answers: [String], maxSelections: UInt8, pollKind: PollKind, editItem: EventTimelineItem) async throws { - if let error = editPollQuestionAnswersMaxSelectionsPollKindEditItemThrowableError { - throw error - } - editPollQuestionAnswersMaxSelectionsPollKindEditItemCallsCount += 1 - editPollQuestionAnswersMaxSelectionsPollKindEditItemReceivedArguments = (question: question, answers: answers, maxSelections: maxSelections, pollKind: pollKind, editItem: editItem) - DispatchQueue.main.async { - self.editPollQuestionAnswersMaxSelectionsPollKindEditItemReceivedInvocations.append((question: question, answers: answers, maxSelections: maxSelections, pollKind: pollKind, editItem: editItem)) - } - try await editPollQuestionAnswersMaxSelectionsPollKindEditItemClosure?(question, answers, maxSelections, pollKind, editItem) - } - //MARK: - endPoll open var endPollPollStartIdTextThrowableError: Error? @@ -19803,16 +20410,16 @@ open class TimelineSDKMock: MatrixRustSDK.Timeline { //MARK: - toggleReaction - open var toggleReactionEventIdKeyThrowableError: Error? - var toggleReactionEventIdKeyUnderlyingCallsCount = 0 - open var toggleReactionEventIdKeyCallsCount: Int { + open var toggleReactionUniqueIdKeyThrowableError: Error? + var toggleReactionUniqueIdKeyUnderlyingCallsCount = 0 + open var toggleReactionUniqueIdKeyCallsCount: Int { get { if Thread.isMainThread { - return toggleReactionEventIdKeyUnderlyingCallsCount + return toggleReactionUniqueIdKeyUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = toggleReactionEventIdKeyUnderlyingCallsCount + returnValue = toggleReactionUniqueIdKeyUnderlyingCallsCount } return returnValue! @@ -19820,31 +20427,31 @@ open class TimelineSDKMock: MatrixRustSDK.Timeline { } set { if Thread.isMainThread { - toggleReactionEventIdKeyUnderlyingCallsCount = newValue + toggleReactionUniqueIdKeyUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - toggleReactionEventIdKeyUnderlyingCallsCount = newValue + toggleReactionUniqueIdKeyUnderlyingCallsCount = newValue } } } } - open var toggleReactionEventIdKeyCalled: Bool { - return toggleReactionEventIdKeyCallsCount > 0 + open var toggleReactionUniqueIdKeyCalled: Bool { + return toggleReactionUniqueIdKeyCallsCount > 0 } - open var toggleReactionEventIdKeyReceivedArguments: (eventId: String, key: String)? - open var toggleReactionEventIdKeyReceivedInvocations: [(eventId: String, key: String)] = [] - open var toggleReactionEventIdKeyClosure: ((String, String) async throws -> Void)? + open var toggleReactionUniqueIdKeyReceivedArguments: (uniqueId: String, key: String)? + open var toggleReactionUniqueIdKeyReceivedInvocations: [(uniqueId: String, key: String)] = [] + open var toggleReactionUniqueIdKeyClosure: ((String, String) async throws -> Void)? - open override func toggleReaction(eventId: String, key: String) async throws { - if let error = toggleReactionEventIdKeyThrowableError { + open override func toggleReaction(uniqueId: String, key: String) async throws { + if let error = toggleReactionUniqueIdKeyThrowableError { throw error } - toggleReactionEventIdKeyCallsCount += 1 - toggleReactionEventIdKeyReceivedArguments = (eventId: eventId, key: key) + toggleReactionUniqueIdKeyCallsCount += 1 + toggleReactionUniqueIdKeyReceivedArguments = (uniqueId: uniqueId, key: key) DispatchQueue.main.async { - self.toggleReactionEventIdKeyReceivedInvocations.append((eventId: eventId, key: key)) + self.toggleReactionUniqueIdKeyReceivedInvocations.append((uniqueId: uniqueId, key: key)) } - try await toggleReactionEventIdKeyClosure?(eventId, key) + try await toggleReactionUniqueIdKeyClosure?(uniqueId, key) } //MARK: - unpinEvent @@ -20452,6 +21059,71 @@ open class TimelineDiffSDKMock: MatrixRustSDK.TimelineDiff { return setReturnValue } } + + //MARK: - truncate + + var truncateUnderlyingCallsCount = 0 + open var truncateCallsCount: Int { + get { + if Thread.isMainThread { + return truncateUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = truncateUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + truncateUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + truncateUnderlyingCallsCount = newValue + } + } + } + } + open var truncateCalled: Bool { + return truncateCallsCount > 0 + } + + var truncateUnderlyingReturnValue: UInt32? + open var truncateReturnValue: UInt32? { + get { + if Thread.isMainThread { + return truncateUnderlyingReturnValue + } else { + var returnValue: UInt32?? = nil + DispatchQueue.main.sync { + returnValue = truncateUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + truncateUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + truncateUnderlyingReturnValue = newValue + } + } + } + } + open var truncateClosure: (() -> UInt32?)? + + open override func truncate() -> UInt32? { + truncateCallsCount += 1 + if let truncateClosure = truncateClosure { + return truncateClosure() + } else { + return truncateReturnValue + } + } } open class TimelineEventSDKMock: MatrixRustSDK.TimelineEvent { init() { diff --git a/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift b/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift new file mode 100644 index 0000000000..86e33a7a48 --- /dev/null +++ b/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift @@ -0,0 +1,155 @@ +// +// Copyright 2023, 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Combine +import Foundation + +enum RoomProxyMockError: Error { + case generic +} + +@MainActor +struct JoinedRoomProxyMockConfiguration { + var id = UUID().uuidString + var name: String? + var topic: String? + var avatarURL: URL? + var isDirect = false + var isSpace = false + var isPublic = false + var isEncrypted = true + var hasOngoingCall = true + var canonicalAlias: String? + var pinnedEventIDs: Set = [] + + var timelineStartReached = false + + var members: [RoomMemberProxyMock] = .allMembers + var ownUserID = RoomMemberProxyMock.mockMe.userID + var inviter: RoomMemberProxyProtocol? + + var canUserInvite = true + var canUserTriggerRoomNotification = false + var canUserJoinCall = true + var canUserPin = true + + var shouldUseAutoUpdatingTimeline = false +} + +extension JoinedRoomProxyMock { + @MainActor + convenience init(_ configuration: JoinedRoomProxyMockConfiguration) { + self.init() + + id = configuration.id + name = configuration.name + topic = configuration.topic + avatar = .room(id: configuration.id, name: configuration.name, avatarURL: configuration.avatarURL) // Note: This doesn't replicate the real proxy logic. + avatarURL = configuration.avatarURL + isDirect = configuration.isDirect + isSpace = configuration.isSpace + isPublic = configuration.isPublic + isEncrypted = configuration.isEncrypted + hasOngoingCall = configuration.hasOngoingCall + canonicalAlias = configuration.canonicalAlias + + underlyingPinnedEventIDs = configuration.pinnedEventIDs + + 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 + + ownUserID = configuration.ownUserID + + membersPublisher = CurrentValueSubject(configuration.members).asCurrentValuePublisher() + typingMembersPublisher = CurrentValueSubject([]).asCurrentValuePublisher() + + joinedMembersCount = configuration.members.filter { $0.membership == .join }.count + activeMembersCount = configuration.members.filter { $0.membership == .join || $0.membership == .invite }.count + + updateMembersClosure = { } + underlyingActionsPublisher = Empty(completeImmediately: false).eraseToAnyPublisher() + setNameClosure = { _ in .success(()) } + setTopicClosure = { _ in .success(()) } + getMemberUserIDClosure = { [weak self] userID in + guard let member = self?.membersPublisher.value.first(where: { $0.userID == userID }) else { + return .failure(.sdkError(RoomProxyMockError.generic)) + } + return .success(member) + } + + resendItemIDReturnValue = .success(()) + ignoreDeviceTrustAndResendDevicesItemIDReturnValue = .success(()) + withdrawVerificationAndResendUserIDsItemIDReturnValue = .success(()) + + flagAsUnreadReturnValue = .success(()) + markAsReadReceiptTypeReturnValue = .success(()) + underlyingIsFavourite = false + flagAsFavouriteReturnValue = .success(()) + + powerLevelsReturnValue = .success(.mock) + applyPowerLevelChangesReturnValue = .success(()) + resetPowerLevelsReturnValue = .success(.mock) + suggestedRoleForClosure = { [weak self] userID in + guard case .success(let member) = await self?.getMember(userID: userID) else { + return .failure(.sdkError(RoomProxyMockError.generic)) + } + return .success(member.role) + } + updatePowerLevelsForUsersReturnValue = .success(()) + canUserUserIDSendStateEventClosure = { [weak self] userID, _ in + .success(self?.membersPublisher.value.first { $0.userID == userID }?.role ?? .user != .user) + } + canUserInviteUserIDReturnValue = .success(configuration.canUserInvite) + canUserRedactOtherUserIDReturnValue = .success(false) + canUserRedactOwnUserIDReturnValue = .success(false) + canUserKickUserIDClosure = { [weak self] userID in + .success(self?.membersPublisher.value.first { $0.userID == userID }?.role ?? .user != .user) + } + canUserBanUserIDClosure = { [weak self] userID in + .success(self?.membersPublisher.value.first { $0.userID == userID }?.role ?? .user != .user) + } + canUserTriggerRoomNotificationUserIDReturnValue = .success(configuration.canUserTriggerRoomNotification) + canUserJoinCallUserIDReturnValue = .success(configuration.canUserJoinCall) + canUserPinOrUnpinUserIDReturnValue = .success(configuration.canUserPin) + + kickUserReturnValue = .success(()) + banUserReturnValue = .success(()) + unbanUserReturnValue = .success(()) + + let widgetDriver = ElementCallWidgetDriverMock() + widgetDriver.underlyingMessagePublisher = .init() + widgetDriver.underlyingActions = PassthroughSubject().eraseToAnyPublisher() + + guard let url = URL(string: "https://call.element.dev/\(UUID().uuidString)#?appPrompt=false") else { + fatalError() + } + + widgetDriver.startBaseURLClientIDColorSchemeReturnValue = .success(url) + + elementCallWidgetDriverDeviceIDReturnValue = widgetDriver + sendCallNotificationIfNeededReturnValue = .success(()) + + matrixToPermalinkReturnValue = .success(.homeDirectory) + matrixToEventPermalinkReturnValue = .success(.homeDirectory) + loadDraftReturnValue = .success(nil) + clearDraftReturnValue = .success(()) + } +} diff --git a/ElementX/Sources/Mocks/NetworkMonitorMock.swift b/ElementX/Sources/Mocks/NetworkMonitorMock.swift index cb9cecf932..617be50090 100644 --- a/ElementX/Sources/Mocks/NetworkMonitorMock.swift +++ b/ElementX/Sources/Mocks/NetworkMonitorMock.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Mocks/NotificationSettingsProxyMock.swift b/ElementX/Sources/Mocks/NotificationSettingsProxyMock.swift index a914fae3cd..59559f8ca8 100644 --- a/ElementX/Sources/Mocks/NotificationSettingsProxyMock.swift +++ b/ElementX/Sources/Mocks/NotificationSettingsProxyMock.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Mocks/PHGPostHogMock.swift b/ElementX/Sources/Mocks/PHGPostHogMock.swift index 14580b3432..c80f138715 100644 --- a/ElementX/Sources/Mocks/PHGPostHogMock.swift +++ b/ElementX/Sources/Mocks/PHGPostHogMock.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Mocks/PollMock.swift b/ElementX/Sources/Mocks/PollMock.swift index 2c0f8bc369..cc3322871b 100644 --- a/ElementX/Sources/Mocks/PollMock.swift +++ b/ElementX/Sources/Mocks/PollMock.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Mocks/RoomDirectorySearchMock.swift b/ElementX/Sources/Mocks/RoomDirectorySearchMock.swift index 0ee20b1404..1a23a37294 100644 --- a/ElementX/Sources/Mocks/RoomDirectorySearchMock.swift +++ b/ElementX/Sources/Mocks/RoomDirectorySearchMock.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Mocks/RoomMemberProxyMock.swift b/ElementX/Sources/Mocks/RoomMemberProxyMock.swift index 4fb81d4e4d..9825257d0a 100644 --- a/ElementX/Sources/Mocks/RoomMemberProxyMock.swift +++ b/ElementX/Sources/Mocks/RoomMemberProxyMock.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Mocks/RoomNotificationSettingsProxyMock.swift b/ElementX/Sources/Mocks/RoomNotificationSettingsProxyMock.swift index b2572e4df2..e8d06a8026 100644 --- a/ElementX/Sources/Mocks/RoomNotificationSettingsProxyMock.swift +++ b/ElementX/Sources/Mocks/RoomNotificationSettingsProxyMock.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Mocks/RoomProxyMock.swift b/ElementX/Sources/Mocks/RoomProxyMock.swift deleted file mode 100644 index 5a3d5ca7d8..0000000000 --- a/ElementX/Sources/Mocks/RoomProxyMock.swift +++ /dev/null @@ -1,163 +0,0 @@ -// -// Copyright 2023 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Combine -import Foundation - -@MainActor -struct RoomProxyMockConfiguration { - var id = UUID().uuidString - var name: String? - var topic: String? - var avatarURL: URL? - var isDirect = false - var isSpace = false - var isPublic = false - var isEncrypted = true - var hasOngoingCall = true - var canonicalAlias: String? - var pinnedEventIDs: Set = [] - - var timelineStartReached = false - - var members: [RoomMemberProxyMock] = .allMembers - var ownUserID = RoomMemberProxyMock.mockMe.userID - var inviter: RoomMemberProxyProtocol? - - var canUserInvite = true - var canUserTriggerRoomNotification = false - var canUserJoinCall = true - var canUserPin = true - - var shouldUseAutoUpdatingTimeline = false -} - -enum RoomProxyMockError: Error { - case generic -} - -extension RoomProxyMock { - @MainActor - convenience init(_ configuration: RoomProxyMockConfiguration) { - self.init() - - id = configuration.id - name = configuration.name - topic = configuration.topic - avatar = .room(id: configuration.id, name: configuration.name, avatarURL: configuration.avatarURL) // Note: This doesn't replicate the real proxy logic. - avatarURL = configuration.avatarURL - isDirect = configuration.isDirect - isSpace = configuration.isSpace - isPublic = configuration.isPublic - isEncrypted = configuration.isEncrypted - hasOngoingCall = configuration.hasOngoingCall - canonicalAlias = configuration.canonicalAlias - - underlyingPinnedEventIDs = configuration.pinnedEventIDs - - 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 - - ownUserID = configuration.ownUserID - membership = .joined - inviterClosure = { configuration.inviter } - - membersPublisher = CurrentValueSubject(configuration.members).asCurrentValuePublisher() - typingMembersPublisher = CurrentValueSubject([]).asCurrentValuePublisher() - - joinedMembersCount = configuration.members.filter { $0.membership == .join }.count - activeMembersCount = configuration.members.filter { $0.membership == .join || $0.membership == .invite }.count - - updateMembersClosure = { } - acceptInvitationClosure = { .success(()) } - underlyingActionsPublisher = Empty(completeImmediately: false).eraseToAnyPublisher() - setNameClosure = { _ in .success(()) } - setTopicClosure = { _ in .success(()) } - getMemberUserIDClosure = { [weak self] userID in - guard let member = self?.membersPublisher.value.first(where: { $0.userID == userID }) else { - return .failure(.sdkError(RoomProxyMockError.generic)) - } - return .success(member) - } - - flagAsUnreadReturnValue = .success(()) - markAsReadReceiptTypeReturnValue = .success(()) - underlyingIsFavourite = false - flagAsFavouriteReturnValue = .success(()) - - powerLevelsReturnValue = .success(.mock) - applyPowerLevelChangesReturnValue = .success(()) - resetPowerLevelsReturnValue = .success(.mock) - suggestedRoleForClosure = { [weak self] userID in - guard case .success(let member) = await self?.getMember(userID: userID) else { - return .failure(.sdkError(RoomProxyMockError.generic)) - } - return .success(member.role) - } - updatePowerLevelsForUsersReturnValue = .success(()) - canUserUserIDSendStateEventClosure = { [weak self] userID, _ in - .success(self?.membersPublisher.value.first { $0.userID == userID }?.role ?? .user != .user) - } - canUserInviteUserIDReturnValue = .success(configuration.canUserInvite) - canUserRedactOtherUserIDReturnValue = .success(false) - canUserRedactOwnUserIDReturnValue = .success(false) - canUserKickUserIDClosure = { [weak self] userID in - .success(self?.membersPublisher.value.first { $0.userID == userID }?.role ?? .user != .user) - } - canUserBanUserIDClosure = { [weak self] userID in - .success(self?.membersPublisher.value.first { $0.userID == userID }?.role ?? .user != .user) - } - canUserTriggerRoomNotificationUserIDReturnValue = .success(configuration.canUserTriggerRoomNotification) - canUserJoinCallUserIDReturnValue = .success(configuration.canUserJoinCall) - canUserPinOrUnpinUserIDReturnValue = .success(configuration.canUserPin) - - kickUserReturnValue = .success(()) - banUserReturnValue = .success(()) - unbanUserReturnValue = .success(()) - - let widgetDriver = ElementCallWidgetDriverMock() - widgetDriver.underlyingMessagePublisher = .init() - widgetDriver.underlyingActions = PassthroughSubject().eraseToAnyPublisher() - - guard let url = URL(string: "https://call.element.dev/\(UUID().uuidString)#?appPrompt=false") else { - fatalError() - } - - widgetDriver.startBaseURLClientIDColorSchemeReturnValue = .success(url) - - elementCallWidgetDriverDeviceIDReturnValue = widgetDriver - sendCallNotificationIfNeeededReturnValue = .success(()) - - matrixToPermalinkReturnValue = .success(.homeDirectory) - matrixToEventPermalinkReturnValue = .success(.homeDirectory) - loadDraftReturnValue = .success(nil) - clearDraftReturnValue = .success(()) - } -} diff --git a/ElementX/Sources/Mocks/RoomSummaryProviderMock.swift b/ElementX/Sources/Mocks/RoomSummaryProviderMock.swift index 3a3084d028..7e47548e0f 100644 --- a/ElementX/Sources/Mocks/RoomSummaryProviderMock.swift +++ b/ElementX/Sources/Mocks/RoomSummaryProviderMock.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Mocks/RoomTimelineControllerFactoryMock.swift b/ElementX/Sources/Mocks/RoomTimelineControllerFactoryMock.swift index b14a2fa362..6dd55f8e35 100644 --- a/ElementX/Sources/Mocks/RoomTimelineControllerFactoryMock.swift +++ b/ElementX/Sources/Mocks/RoomTimelineControllerFactoryMock.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Mocks/RoomTimelineProviderMock.swift b/ElementX/Sources/Mocks/RoomTimelineProviderMock.swift index 1a13ce597f..0e671fcfe0 100644 --- a/ElementX/Sources/Mocks/RoomTimelineProviderMock.swift +++ b/ElementX/Sources/Mocks/RoomTimelineProviderMock.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -35,7 +26,7 @@ class AutoUpdatingRoomTimelineProviderMock: RoomTimelineProvider { } super.init(timeline: timelineMock, - isLive: true, + kind: .live, paginationStatePublisher: innerPaginationStatePublisher.eraseToAnyPublisher()) Task.detached { diff --git a/ElementX/Sources/Mocks/SessionVerificationControllerProxyMock.swift b/ElementX/Sources/Mocks/SessionVerificationControllerProxyMock.swift index 3af649d260..377404e7a8 100644 --- a/ElementX/Sources/Mocks/SessionVerificationControllerProxyMock.swift +++ b/ElementX/Sources/Mocks/SessionVerificationControllerProxyMock.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Mocks/TimelineItemMock.swift b/ElementX/Sources/Mocks/TimelineItemMock.swift index ec4efc2461..82138364ea 100644 --- a/ElementX/Sources/Mocks/TimelineItemMock.swift +++ b/ElementX/Sources/Mocks/TimelineItemMock.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Mocks/UserIndicatorControllerMock.swift b/ElementX/Sources/Mocks/UserIndicatorControllerMock.swift index 77da87fcc3..e332da9a38 100644 --- a/ElementX/Sources/Mocks/UserIndicatorControllerMock.swift +++ b/ElementX/Sources/Mocks/UserIndicatorControllerMock.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Mocks/UserProfile+Mock.swift b/ElementX/Sources/Mocks/UserProfile+Mock.swift index 22073bf7a0..c0bfc71155 100644 --- a/ElementX/Sources/Mocks/UserProfile+Mock.swift +++ b/ElementX/Sources/Mocks/UserProfile+Mock.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Mocks/UserSessionMock.swift b/ElementX/Sources/Mocks/UserSessionMock.swift index 8a291eec6d..059b0b07f2 100644 --- a/ElementX/Sources/Mocks/UserSessionMock.swift +++ b/ElementX/Sources/Mocks/UserSessionMock.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Other/AccessibilityIdentifiers.swift b/ElementX/Sources/Other/AccessibilityIdentifiers.swift index f714ac91b1..e78721e64a 100644 --- a/ElementX/Sources/Other/AccessibilityIdentifiers.swift +++ b/ElementX/Sources/Other/AccessibilityIdentifiers.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -41,7 +32,6 @@ enum A11yIdentifiers { static let roomMemberDetailsScreen = RoomMemberDetailsScreen() static let createRoomScreen = CreateRoomScreen() static let inviteUsersScreen = InviteUsersScreen() - static let migrationScreen = MigrationScreen() static let notificationSettingsScreen = NotificationSettingsScreen() static let notificationSettingsEditScreen = NotificationSettingsEditScreen() static let pollFormScreen = PollFormScreen() @@ -248,10 +238,6 @@ enum A11yIdentifiers { "\(optionPrefix)-\(index)" } } - - struct MigrationScreen { - let message = "migration_screen-message" - } struct NotificationSettingsScreen { let fixMismatchConfiguration = "notification_settings_screen-fix_mismatch_configuration" diff --git a/ElementX/Sources/Other/Analytics/ScreenTrackerViewModifier.swift b/ElementX/Sources/Other/Analytics/ScreenTrackerViewModifier.swift index 73dfac54de..742162e7ab 100644 --- a/ElementX/Sources/Other/Analytics/ScreenTrackerViewModifier.swift +++ b/ElementX/Sources/Other/Analytics/ScreenTrackerViewModifier.swift @@ -1,17 +1,8 @@ // -// Copyright 2021 New Vector Ltd +// Copyright 2021-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import AnalyticsEvents diff --git a/ElementX/Sources/Other/AppAppearance.swift b/ElementX/Sources/Other/AppAppearance.swift index c7607aa19d..fe77c54215 100644 --- a/ElementX/Sources/Other/AppAppearance.swift +++ b/ElementX/Sources/Other/AppAppearance.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/AvatarSize.swift b/ElementX/Sources/Other/AvatarSize.swift index 18803f32bf..aa1b477b1c 100644 --- a/ElementX/Sources/Other/AvatarSize.swift +++ b/ElementX/Sources/Other/AvatarSize.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/CancellableTask.swift b/ElementX/Sources/Other/CancellableTask.swift index 8370ba866c..17862c770c 100644 --- a/ElementX/Sources/Other/CancellableTask.swift +++ b/ElementX/Sources/Other/CancellableTask.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/CollapsibleFlowLayout/CollapsibleReactionLayout.swift b/ElementX/Sources/Other/CollapsibleFlowLayout/CollapsibleReactionLayout.swift index 8718797682..e0d8d6e49d 100644 --- a/ElementX/Sources/Other/CollapsibleFlowLayout/CollapsibleReactionLayout.swift +++ b/ElementX/Sources/Other/CollapsibleFlowLayout/CollapsibleReactionLayout.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/Consumable.swift b/ElementX/Sources/Other/Consumable.swift index 15716bb748..a1a5f7aa7f 100644 --- a/ElementX/Sources/Other/Consumable.swift +++ b/ElementX/Sources/Other/Consumable.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/CurrentValuePublisher.swift b/ElementX/Sources/Other/CurrentValuePublisher.swift index 495c9c63de..ff3778f784 100644 --- a/ElementX/Sources/Other/CurrentValuePublisher.swift +++ b/ElementX/Sources/Other/CurrentValuePublisher.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Other/EffectsScene/EffectsScene.swift b/ElementX/Sources/Other/EffectsScene/EffectsScene.swift index 58f0e0bb17..73e00bcdda 100644 --- a/ElementX/Sources/Other/EffectsScene/EffectsScene.swift +++ b/ElementX/Sources/Other/EffectsScene/EffectsScene.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SceneKit diff --git a/ElementX/Sources/Other/EffectsScene/EffectsView.swift b/ElementX/Sources/Other/EffectsScene/EffectsView.swift index f8d0af3721..6012948158 100644 --- a/ElementX/Sources/Other/EffectsScene/EffectsView.swift +++ b/ElementX/Sources/Other/EffectsScene/EffectsView.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SceneKit diff --git a/ElementX/Sources/Other/EmojiDetection.swift b/ElementX/Sources/Other/EmojiDetection.swift index b8056ba56e..aaa5a78535 100644 --- a/ElementX/Sources/Other/EmojiDetection.swift +++ b/ElementX/Sources/Other/EmojiDetection.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/ExpiringTaskRunner.swift b/ElementX/Sources/Other/ExpiringTaskRunner.swift index e28a160821..cde7882859 100644 --- a/ElementX/Sources/Other/ExpiringTaskRunner.swift +++ b/ElementX/Sources/Other/ExpiringTaskRunner.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Extensions/AVMetadataMachineReadableCodeObject.swift b/ElementX/Sources/Other/Extensions/AVMetadataMachineReadableCodeObject.swift index 770957f202..0dac597e30 100644 --- a/ElementX/Sources/Other/Extensions/AVMetadataMachineReadableCodeObject.swift +++ b/ElementX/Sources/Other/Extensions/AVMetadataMachineReadableCodeObject.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // // Helpers to remove ECI headers from QR Code raw data diff --git a/ElementX/Sources/Other/Extensions/Alert.swift b/ElementX/Sources/Other/Extensions/Alert.swift index e32748911f..d9bdb16db3 100644 --- a/ElementX/Sources/Other/Extensions/Alert.swift +++ b/ElementX/Sources/Other/Extensions/Alert.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/Extensions/Array.swift b/ElementX/Sources/Other/Extensions/Array.swift index 26830cb57c..7622916e85 100644 --- a/ElementX/Sources/Other/Extensions/Array.swift +++ b/ElementX/Sources/Other/Extensions/Array.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Extensions/AsyncSequence.swift b/ElementX/Sources/Other/Extensions/AsyncSequence.swift index 3de8a6e026..4799f1ac6a 100644 --- a/ElementX/Sources/Other/Extensions/AsyncSequence.swift +++ b/ElementX/Sources/Other/Extensions/AsyncSequence.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // extension AsyncSequence { diff --git a/ElementX/Sources/Other/Extensions/AttributedString.swift b/ElementX/Sources/Other/Extensions/AttributedString.swift index dbe7fd7427..7f146f1ae5 100644 --- a/ElementX/Sources/Other/Extensions/AttributedString.swift +++ b/ElementX/Sources/Other/Extensions/AttributedString.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Extensions/Bundle.swift b/ElementX/Sources/Other/Extensions/Bundle.swift index 465c43a7e0..efd17348f8 100644 --- a/ElementX/Sources/Other/Extensions/Bundle.swift +++ b/ElementX/Sources/Other/Extensions/Bundle.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Extensions/ClientBuilder.swift b/ElementX/Sources/Other/Extensions/ClientBuilder.swift index 635f9acb8e..586fa4c201 100644 --- a/ElementX/Sources/Other/Extensions/ClientBuilder.swift +++ b/ElementX/Sources/Other/Extensions/ClientBuilder.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -22,18 +13,19 @@ extension ClientBuilder { static func baseBuilder(setupEncryption: Bool = true, httpProxy: String? = nil, slidingSync: ClientBuilderSlidingSync, - slidingSyncProxy: URL? = nil, sessionDelegate: ClientSessionDelegate, - appHooks: AppHooks) -> ClientBuilder { + appHooks: AppHooks, + invisibleCryptoEnabled: Bool) -> ClientBuilder { var builder = ClientBuilder() - .slidingSyncProxy(slidingSyncProxy: slidingSyncProxy?.absoluteString) .enableCrossProcessRefreshLock(processId: InfoPlistReader.main.bundleIdentifier, sessionDelegate: sessionDelegate) .userAgent(userAgent: UserAgentBuilder.makeASCIIUserAgent()) + .requestConfig(config: .init(retryLimit: 0, timeout: 30000, maxConcurrentRequests: nil, retryTimeout: nil)) builder = switch slidingSync { case .restored: builder - case .discovered: builder.requiresSlidingSync() - case .simplified: builder.simplifiedSlidingSync(enable: true) + case .discoverProxy: builder.slidingSyncVersionBuilder(versionBuilder: .discoverProxy) + case .discoverNative: builder.slidingSyncVersionBuilder(versionBuilder: .discoverNative) + case .forceNative: builder.slidingSyncVersionBuilder(versionBuilder: .native) } if setupEncryption { @@ -41,6 +33,12 @@ extension ClientBuilder { .autoEnableCrossSigning(autoEnableCrossSigning: true) .backupDownloadStrategy(backupDownloadStrategy: .afterDecryptionFailure) .autoEnableBackups(autoEnableBackups: true) + + if invisibleCryptoEnabled { + builder = builder.roomKeyRecipientStrategy(strategy: CollectStrategy.identityBasedStrategy) + } else { + builder = builder.roomKeyRecipientStrategy(strategy: .deviceBasedStrategy(onlyAllowTrustedDevices: false, errorOnVerifiedUserProblem: true)) + } } if let httpProxy { @@ -55,7 +53,9 @@ enum ClientBuilderSlidingSync { /// The proxy will be supplied when restoring the Session. case restored /// A proxy must be discovered whilst building the session. - case discovered - /// Use Simplified Sliding Sync (discovery isn't a thing yet). - case simplified + case discoverProxy + /// Native sliding sync must be discovered whilst building the session. + case discoverNative + /// Forces native sliding sync without discovering it. + case forceNative } diff --git a/ElementX/Sources/Other/Extensions/Collection.swift b/ElementX/Sources/Other/Extensions/Collection.swift index 710e4dc21f..4225df216a 100644 --- a/ElementX/Sources/Other/Extensions/Collection.swift +++ b/ElementX/Sources/Other/Extensions/Collection.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Extensions/Comparable.swift b/ElementX/Sources/Other/Extensions/Comparable.swift index 03277b42d1..f7d7cf9ed3 100644 --- a/ElementX/Sources/Other/Extensions/Comparable.swift +++ b/ElementX/Sources/Other/Extensions/Comparable.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // extension Comparable { diff --git a/ElementX/Sources/Other/Extensions/CompoundIcon.swift b/ElementX/Sources/Other/Extensions/CompoundIcon.swift index 95afc59275..5ba8f0fe53 100644 --- a/ElementX/Sources/Other/Extensions/CompoundIcon.swift +++ b/ElementX/Sources/Other/Extensions/CompoundIcon.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Other/Extensions/ConfirmationDialog.swift b/ElementX/Sources/Other/Extensions/ConfirmationDialog.swift index b275da1023..ebaa2c5eb5 100644 --- a/ElementX/Sources/Other/Extensions/ConfirmationDialog.swift +++ b/ElementX/Sources/Other/Extensions/ConfirmationDialog.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/Extensions/Data.swift b/ElementX/Sources/Other/Extensions/Data.swift index 4a99299c8b..95c749685a 100644 --- a/ElementX/Sources/Other/Extensions/Data.swift +++ b/ElementX/Sources/Other/Extensions/Data.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Extensions/Date.swift b/ElementX/Sources/Other/Extensions/Date.swift index f37a95aeb5..791e57dc52 100644 --- a/ElementX/Sources/Other/Extensions/Date.swift +++ b/ElementX/Sources/Other/Extensions/Date.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Extensions/Dictionary.swift b/ElementX/Sources/Other/Extensions/Dictionary.swift index b26a585c50..2fe7ddc8f3 100644 --- a/ElementX/Sources/Other/Extensions/Dictionary.swift +++ b/ElementX/Sources/Other/Extensions/Dictionary.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Extensions/Duration.swift b/ElementX/Sources/Other/Extensions/Duration.swift index c562453032..caa10c551e 100644 --- a/ElementX/Sources/Other/Extensions/Duration.swift +++ b/ElementX/Sources/Other/Extensions/Duration.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Extensions/Encodable.swift b/ElementX/Sources/Other/Extensions/Encodable.swift index 7c0c4e2400..7b91c3ca2d 100644 --- a/ElementX/Sources/Other/Extensions/Encodable.swift +++ b/ElementX/Sources/Other/Extensions/Encodable.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Extensions/FileManager.swift b/ElementX/Sources/Other/Extensions/FileManager.swift index 7d9336c091..0709dec3a4 100644 --- a/ElementX/Sources/Other/Extensions/FileManager.swift +++ b/ElementX/Sources/Other/Extensions/FileManager.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -66,4 +57,8 @@ extension FileManager { return size } + + func numberOfItems(at url: URL) throws -> Int { + try contentsOfDirectory(at: url, includingPropertiesForKeys: nil).count + } } diff --git a/ElementX/Sources/Other/Extensions/ImageCache.swift b/ElementX/Sources/Other/Extensions/ImageCache.swift index badb9f27b2..83afd20508 100644 --- a/ElementX/Sources/Other/Extensions/ImageCache.swift +++ b/ElementX/Sources/Other/Extensions/ImageCache.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Extensions/Label.swift b/ElementX/Sources/Other/Extensions/Label.swift index 22d9de6800..09c27664e9 100644 --- a/ElementX/Sources/Other/Extensions/Label.swift +++ b/ElementX/Sources/Other/Extensions/Label.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Other/Extensions/LayoutDirection.swift b/ElementX/Sources/Other/Extensions/LayoutDirection.swift index 53a4a33b87..c254a0a969 100644 --- a/ElementX/Sources/Other/Extensions/LayoutDirection.swift +++ b/ElementX/Sources/Other/Extensions/LayoutDirection.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/Extensions/MapTiler.swift b/ElementX/Sources/Other/Extensions/MapTiler.swift index 4af1c3b365..0cb5c38111 100644 --- a/ElementX/Sources/Other/Extensions/MapTiler.swift +++ b/ElementX/Sources/Other/Extensions/MapTiler.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Extensions/NSItemProvider.swift b/ElementX/Sources/Other/Extensions/NSItemProvider.swift index 6079ec8f06..fef3478dbb 100644 --- a/ElementX/Sources/Other/Extensions/NSItemProvider.swift +++ b/ElementX/Sources/Other/Extensions/NSItemProvider.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Extensions/NSRegularExpresion.swift b/ElementX/Sources/Other/Extensions/NSRegularExpresion.swift index 56ab3aaa5d..9525979767 100644 --- a/ElementX/Sources/Other/Extensions/NSRegularExpresion.swift +++ b/ElementX/Sources/Other/Extensions/NSRegularExpresion.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Extensions/OrderedSet.swift b/ElementX/Sources/Other/Extensions/OrderedSet.swift index 6eff263a05..ad8b0d6551 100644 --- a/ElementX/Sources/Other/Extensions/OrderedSet.swift +++ b/ElementX/Sources/Other/Extensions/OrderedSet.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Extensions/PlatformViewVersionPredicate.swift b/ElementX/Sources/Other/Extensions/PlatformViewVersionPredicate.swift index 664e8ce243..879af5a8ea 100644 --- a/ElementX/Sources/Other/Extensions/PlatformViewVersionPredicate.swift +++ b/ElementX/Sources/Other/Extensions/PlatformViewVersionPredicate.swift @@ -1,43 +1,27 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // -import UIKit - +import SwiftUI import SwiftUIIntrospect -extension PlatformViewVersionPredicate { - static var supportedVersions: Self { - .iOS(.v16, .v17) - } -} - extension PlatformViewVersionPredicate { static var supportedVersions: Self { - .iOS(.v16, .v17) + .iOS(.v16, .v17, .v18) } } extension PlatformViewVersionPredicate { static var supportedVersions: Self { - .iOS(.v16, .v17) + .iOS(.v16, .v17, .v18) } } extension PlatformViewVersionPredicate { static var supportedVersions: Self { - .iOS(.v16, .v17) + .iOS(.v16, .v17, .v18) } } diff --git a/ElementX/Sources/Other/Extensions/ProposedViewSize.swift b/ElementX/Sources/Other/Extensions/ProposedViewSize.swift index a1fd7fa2d7..17067d58c6 100644 --- a/ElementX/Sources/Other/Extensions/ProposedViewSize.swift +++ b/ElementX/Sources/Other/Extensions/ProposedViewSize.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/Extensions/Publisher.swift b/ElementX/Sources/Other/Extensions/Publisher.swift index eb89c959a7..405eeceebb 100644 --- a/ElementX/Sources/Other/Extensions/Publisher.swift +++ b/ElementX/Sources/Other/Extensions/Publisher.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Other/Extensions/Section.swift b/ElementX/Sources/Other/Extensions/Section.swift index a0b483f17c..122759bf04 100644 --- a/ElementX/Sources/Other/Extensions/Section.swift +++ b/ElementX/Sources/Other/Extensions/Section.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/Extensions/Snapshotting.swift b/ElementX/Sources/Other/Extensions/Snapshotting.swift new file mode 100644 index 0000000000..77a968a15f --- /dev/null +++ b/ElementX/Sources/Other/Extensions/Snapshotting.swift @@ -0,0 +1,58 @@ +// +// Copyright 2024 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import SwiftUI + +public struct SnapshotDelayPreferenceKey: PreferenceKey { + public static var defaultValue: TimeInterval = 0.0 + + public static func reduce(value: inout TimeInterval, nextValue: () -> TimeInterval) { + value = nextValue() + } +} + +public struct SnapshotPrecisionPreferenceKey: PreferenceKey { + public static var defaultValue: Float = 1.0 + + public static func reduce(value: inout Float, nextValue: () -> Float) { + value = nextValue() + } +} + +public struct SnapshotPerceptualPrecisionPreferenceKey: PreferenceKey { + public static var defaultValue: Float = 1.0 + + public static func reduce(value: inout Float, nextValue: () -> Float) { + value = nextValue() + } +} + +public extension SwiftUI.View { + /// Use this modifier when you want to apply snapshot-specific preferences, + /// like delay and precision, to the view. + /// These preferences can then be retrieved and used elsewhere in your view hierarchy. + /// + /// - Parameters: + /// - delay: The delay time in seconds that you want to set as a preference to the View. + /// - precision: The percentage of pixels that must match. + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. 98-99% mimics the precision of the human eye. + @inlinable + func snapshotPreferences(delay: TimeInterval = .zero, precision: Float = 1.0, perceptualPrecision: Float = 1.0) -> some SwiftUI.View { + preference(key: SnapshotDelayPreferenceKey.self, value: delay) + .preference(key: SnapshotPrecisionPreferenceKey.self, value: precision) + .preference(key: SnapshotPerceptualPrecisionPreferenceKey.self, value: perceptualPrecision) + } +} diff --git a/ElementX/Sources/Other/Extensions/String.swift b/ElementX/Sources/Other/Extensions/String.swift index a4479fb7c0..58caff4888 100644 --- a/ElementX/Sources/Other/Extensions/String.swift +++ b/ElementX/Sources/Other/Extensions/String.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/Extensions/Task.swift b/ElementX/Sources/Other/Extensions/Task.swift index a58731bccc..1838f4f575 100644 --- a/ElementX/Sources/Other/Extensions/Task.swift +++ b/ElementX/Sources/Other/Extensions/Task.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Other/Extensions/UIDevice.swift b/ElementX/Sources/Other/Extensions/UIDevice.swift index cf3b0c7ee6..b2b496bad6 100644 --- a/ElementX/Sources/Other/Extensions/UIDevice.swift +++ b/ElementX/Sources/Other/Extensions/UIDevice.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UIKit diff --git a/ElementX/Sources/Other/Extensions/UIView.swift b/ElementX/Sources/Other/Extensions/UIView.swift new file mode 100644 index 0000000000..1e32eccae7 --- /dev/null +++ b/ElementX/Sources/Other/Extensions/UIView.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 SwiftUI + +extension UIView { + func addMatchedSubview(_ subview: UIView) { + addSubview(subview) + subview.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + subview.topAnchor.constraint(equalTo: topAnchor), + subview.leadingAnchor.constraint(equalTo: leadingAnchor), + subview.trailingAnchor.constraint(equalTo: trailingAnchor), + subview.bottomAnchor.constraint(equalTo: bottomAnchor) + ]) + } +} diff --git a/ElementX/Sources/Other/Extensions/UNNotificationContent.swift b/ElementX/Sources/Other/Extensions/UNNotificationContent.swift index 4440021229..2fa224d5a6 100644 --- a/ElementX/Sources/Other/Extensions/UNNotificationContent.swift +++ b/ElementX/Sources/Other/Extensions/UNNotificationContent.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -44,6 +35,10 @@ extension UNNotificationContent { @objc var roomID: String? { userInfo[NotificationConstants.UserInfoKey.roomIdentifier] as? String } + + @objc var eventID: String? { + userInfo[NotificationConstants.UserInfoKey.eventIdentifier] as? String + } } extension UNMutableNotificationContent { @@ -64,6 +59,15 @@ extension UNMutableNotificationContent { userInfo[NotificationConstants.UserInfoKey.roomIdentifier] = newValue } } + + override var eventID: String? { + get { + userInfo[NotificationConstants.UserInfoKey.eventIdentifier] as? String + } + set { + userInfo[NotificationConstants.UserInfoKey.eventIdentifier] = newValue + } + } func addMediaAttachment(using mediaProvider: MediaProviderProtocol?, mediaSource: MediaSourceProxy) async -> UNMutableNotificationContent { diff --git a/ElementX/Sources/Other/Extensions/URL.swift b/ElementX/Sources/Other/Extensions/URL.swift index 0776498ff5..e23d72aea5 100644 --- a/ElementX/Sources/Other/Extensions/URL.swift +++ b/ElementX/Sources/Other/Extensions/URL.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -68,6 +59,22 @@ extension URL: ExpressibleByStringLiteral { return url } + /// The base directory where all application support data is stored. + static var cachesBaseDirectory: URL { + let url = appGroupContainerDirectory + .appendingPathComponent("Library", isDirectory: true) + .appendingPathComponent("Caches", isDirectory: true) + .appendingPathComponent(InfoPlistReader.main.baseBundleIdentifier, isDirectory: true) + .appendingPathComponent("Sessions", isDirectory: true) + + try? FileManager.default.createDirectoryIfNeeded(at: url) + + // Caches are excluded from backups automatically anyway. + // https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html + + return url + } + var globalProxy: String? { if let proxySettingsUnmanaged = CFNetworkCopySystemProxySettings() { let proxySettings = proxySettingsUnmanaged.takeRetainedValue() diff --git a/ElementX/Sources/Other/Extensions/URLComponents.swift b/ElementX/Sources/Other/Extensions/URLComponents.swift index d0ffdc33be..d5cac0ada9 100644 --- a/ElementX/Sources/Other/Extensions/URLComponents.swift +++ b/ElementX/Sources/Other/Extensions/URLComponents.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Extensions/URLSession.swift b/ElementX/Sources/Other/Extensions/URLSession.swift index f9464cd318..d3f51f7aa1 100644 --- a/ElementX/Sources/Other/Extensions/URLSession.swift +++ b/ElementX/Sources/Other/Extensions/URLSession.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Extensions/UTType.swift b/ElementX/Sources/Other/Extensions/UTType.swift index b92e825e2d..961010755c 100644 --- a/ElementX/Sources/Other/Extensions/UTType.swift +++ b/ElementX/Sources/Other/Extensions/UTType.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UniformTypeIdentifiers diff --git a/ElementX/Sources/Other/Extensions/XCUIElement.swift b/ElementX/Sources/Other/Extensions/XCUIElement.swift index 12d69ba55c..bb345b3c03 100644 --- a/ElementX/Sources/Other/Extensions/XCUIElement.swift +++ b/ElementX/Sources/Other/Extensions/XCUIElement.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilder.swift b/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilder.swift index 7ba62e5118..890deefe97 100644 --- a/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilder.swift +++ b/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilder.swift @@ -1,19 +1,11 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // +import Compound import DTCoreText import Foundation import LRUCache @@ -276,7 +268,7 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol { attributedString.enumerateAttribute(.backgroundColor, in: .init(location: 0, length: attributedString.length), options: []) { value, range, _ in if let value = value as? UIColor, value == temporaryCodeBlockMarkingColor { - attributedString.addAttribute(.backgroundColor, value: UIColor(.compound._bgCodeBlock) as Any, range: range) + attributedString.addAttribute(.backgroundColor, value: UIColor.compound._bgCodeBlock as Any, range: range) attributedString.removeAttribute(.link, range: range) } } diff --git a/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilderProtocol.swift b/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilderProtocol.swift index 4ed817ca3c..59456ac647 100644 --- a/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilderProtocol.swift +++ b/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilderProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/HTMLParsing/DTHTMLElement+AttributedStringBuilder.swift b/ElementX/Sources/Other/HTMLParsing/DTHTMLElement+AttributedStringBuilder.swift index be8bb482b4..806269ccba 100644 --- a/ElementX/Sources/Other/HTMLParsing/DTHTMLElement+AttributedStringBuilder.swift +++ b/ElementX/Sources/Other/HTMLParsing/DTHTMLElement+AttributedStringBuilder.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import DTCoreText diff --git a/ElementX/Sources/Other/HTMLParsing/ElementXAttributeScope.swift b/ElementX/Sources/Other/HTMLParsing/ElementXAttributeScope.swift index 67519f28f3..fcb635b53f 100644 --- a/ElementX/Sources/Other/HTMLParsing/ElementXAttributeScope.swift +++ b/ElementX/Sources/Other/HTMLParsing/ElementXAttributeScope.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/HTMLParsing/UIFont+AttributedStringBuilder.h b/ElementX/Sources/Other/HTMLParsing/UIFont+AttributedStringBuilder.h index 3c574509c8..a7cf093c2d 100644 --- a/ElementX/Sources/Other/HTMLParsing/UIFont+AttributedStringBuilder.h +++ b/ElementX/Sources/Other/HTMLParsing/UIFont+AttributedStringBuilder.h @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @import UIKit; diff --git a/ElementX/Sources/Other/HTMLParsing/UIFont+AttributedStringBuilder.m b/ElementX/Sources/Other/HTMLParsing/UIFont+AttributedStringBuilder.m index 9c24400ac0..bedb11bcb1 100644 --- a/ElementX/Sources/Other/HTMLParsing/UIFont+AttributedStringBuilder.m +++ b/ElementX/Sources/Other/HTMLParsing/UIFont+AttributedStringBuilder.m @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // #import "UIFont+AttributedStringBuilder.h" diff --git a/ElementX/Sources/Other/InfoPlistReader.swift b/ElementX/Sources/Other/InfoPlistReader.swift index 2f561cf9d9..ce8e529db2 100644 --- a/ElementX/Sources/Other/InfoPlistReader.swift +++ b/ElementX/Sources/Other/InfoPlistReader.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Logging/MXLog.swift b/ElementX/Sources/Other/Logging/MXLog.swift index e022420b89..652c257f00 100644 --- a/ElementX/Sources/Other/Logging/MXLog.swift +++ b/ElementX/Sources/Other/Logging/MXLog.swift @@ -1,17 +1,9 @@ // -// Copyright 2021 The Matrix.org Foundation C.I.C +// Copyright 2024 New Vector Ltd. +// Copyright 2021-2024 The Matrix.org Foundation C.I.C // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Logging/RustTracing.swift b/ElementX/Sources/Other/Logging/RustTracing.swift index 3b46c171de..243d2d9e81 100644 --- a/ElementX/Sources/Other/Logging/RustTracing.swift +++ b/ElementX/Sources/Other/Logging/RustTracing.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Logging/TracingConfiguration.swift b/ElementX/Sources/Other/Logging/TracingConfiguration.swift index 795704d5f0..3ff5250de0 100644 --- a/ElementX/Sources/Other/Logging/TracingConfiguration.swift +++ b/ElementX/Sources/Other/Logging/TracingConfiguration.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Collections @@ -76,7 +67,7 @@ struct TracingConfiguration { } static let targets: OrderedDictionary = [ - .common: .info, + .common: .info, // Never set this lower than info - 3rd-party crates may start logging user data. .elementx: .info, .hyper: .warn, .matrix_sdk_ffi: .info, @@ -115,7 +106,7 @@ struct TracingConfiguration { let overrides = Self.targets.keys.reduce(into: [Target: LogLevel]()) { partialResult, target in // Keep the defaults here - let ignoredTargets: [Target] = [.common, + let ignoredTargets: [Target] = [.common, // Never remove common from the ignored targets (see above for more info). .hyper, .matrix_sdk_ffi, .matrix_sdk_oidc, diff --git a/ElementX/Sources/Other/MapLibre/LocationAnnotation.swift b/ElementX/Sources/Other/MapLibre/LocationAnnotation.swift index 915bf8c254..971b0a9a07 100644 --- a/ElementX/Sources/Other/MapLibre/LocationAnnotation.swift +++ b/ElementX/Sources/Other/MapLibre/LocationAnnotation.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/MapLibre/MapLibreMapView.swift b/ElementX/Sources/Other/MapLibre/MapLibreMapView.swift index 14c34f2a15..c2875385cd 100644 --- a/ElementX/Sources/Other/MapLibre/MapLibreMapView.swift +++ b/ElementX/Sources/Other/MapLibre/MapLibreMapView.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -182,7 +173,7 @@ extension MapLibreMapView { } func mapView(_ mapView: MGLMapView, regionDidChangeAnimated animated: Bool) { - // Fixes: "Publishing changes from within view updates is not allowed, this will cause undefined behavior." + // Avoid `Publishing changes from within view update` warnings DispatchQueue.main.async { [mapLibreView] in mapLibreView.mapCenterCoordinate = mapView.centerCoordinate } diff --git a/ElementX/Sources/Other/MapLibre/MapLibreModels.swift b/ElementX/Sources/Other/MapLibre/MapLibreModels.swift index bbef15fbc9..ac5c01974c 100644 --- a/ElementX/Sources/Other/MapLibre/MapLibreModels.swift +++ b/ElementX/Sources/Other/MapLibre/MapLibreModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/MapLibre/MapLibreStaticMapView.swift b/ElementX/Sources/Other/MapLibre/MapLibreStaticMapView.swift index 5f23659379..3942668e62 100644 --- a/ElementX/Sources/Other/MapLibre/MapLibreStaticMapView.swift +++ b/ElementX/Sources/Other/MapLibre/MapLibreStaticMapView.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import CoreLocation diff --git a/ElementX/Sources/Other/MapLibre/MapTilerAuthorization.swift b/ElementX/Sources/Other/MapLibre/MapTilerAuthorization.swift index bd5cd71e40..1c35205af1 100644 --- a/ElementX/Sources/Other/MapLibre/MapTilerAuthorization.swift +++ b/ElementX/Sources/Other/MapLibre/MapTilerAuthorization.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/MapLibre/MapTilerStaticMap.swift b/ElementX/Sources/Other/MapLibre/MapTilerStaticMap.swift index 6bb6d594f6..1fd2651aed 100644 --- a/ElementX/Sources/Other/MapLibre/MapTilerStaticMap.swift +++ b/ElementX/Sources/Other/MapLibre/MapTilerStaticMap.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import CoreLocation diff --git a/ElementX/Sources/Other/MapLibre/MapTilerStaticMapProtocol.swift b/ElementX/Sources/Other/MapLibre/MapTilerStaticMapProtocol.swift index 790fdc70bb..a6f333918d 100644 --- a/ElementX/Sources/Other/MapLibre/MapTilerStaticMapProtocol.swift +++ b/ElementX/Sources/Other/MapLibre/MapTilerStaticMapProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import CoreLocation diff --git a/ElementX/Sources/Other/MapLibre/MapTilerStyle.swift b/ElementX/Sources/Other/MapLibre/MapTilerStyle.swift index bc5005a0bc..5eed02a75f 100644 --- a/ElementX/Sources/Other/MapLibre/MapTilerStyle.swift +++ b/ElementX/Sources/Other/MapLibre/MapTilerStyle.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // /// The style for a map. diff --git a/ElementX/Sources/Other/MapLibre/MapTilerStyleBuilder.swift b/ElementX/Sources/Other/MapLibre/MapTilerStyleBuilder.swift index cb7fc4f70b..a286a254e9 100644 --- a/ElementX/Sources/Other/MapLibre/MapTilerStyleBuilder.swift +++ b/ElementX/Sources/Other/MapLibre/MapTilerStyleBuilder.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/MapLibre/MapTilerStyleBuilderProtocol.swift b/ElementX/Sources/Other/MapLibre/MapTilerStyleBuilderProtocol.swift index 62f0f0f68b..120c92faa1 100644 --- a/ElementX/Sources/Other/MapLibre/MapTilerStyleBuilderProtocol.swift +++ b/ElementX/Sources/Other/MapLibre/MapTilerStyleBuilderProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/MatrixEntityRegex.swift b/ElementX/Sources/Other/MatrixEntityRegex.swift index 3959a88d60..ccdd62c6cd 100644 --- a/ElementX/Sources/Other/MatrixEntityRegex.swift +++ b/ElementX/Sources/Other/MatrixEntityRegex.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/NetworkMonitor/NetworkMonitor.swift b/ElementX/Sources/Other/NetworkMonitor/NetworkMonitor.swift index ca90675aa5..ab62e5d8ba 100644 --- a/ElementX/Sources/Other/NetworkMonitor/NetworkMonitor.swift +++ b/ElementX/Sources/Other/NetworkMonitor/NetworkMonitor.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Other/NetworkMonitor/NetworkMonitorProtocol.swift b/ElementX/Sources/Other/NetworkMonitor/NetworkMonitorProtocol.swift index 7d7fc7d089..f6c9ba8cd0 100644 --- a/ElementX/Sources/Other/NetworkMonitor/NetworkMonitorProtocol.swift +++ b/ElementX/Sources/Other/NetworkMonitor/NetworkMonitorProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Pills/MentionBuilder.swift b/ElementX/Sources/Other/Pills/MentionBuilder.swift index 715b5ec8b6..889fe90324 100644 --- a/ElementX/Sources/Other/Pills/MentionBuilder.swift +++ b/ElementX/Sources/Other/Pills/MentionBuilder.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Pills/MessageText.swift b/ElementX/Sources/Other/Pills/MessageText.swift index 35a9d1c779..b622027816 100644 --- a/ElementX/Sources/Other/Pills/MessageText.swift +++ b/ElementX/Sources/Other/Pills/MessageText.swift @@ -1,24 +1,15 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import MatrixRustSDK import SwiftUI final class MessageTextView: UITextView, PillAttachmentViewProviderDelegate { - var roomContext: RoomScreenViewModel.Context? + var timelineContext: TimelineViewModel.Context? var updateClosure: (() -> Void)? private var pillViews = NSHashTable.weakObjects() @@ -54,7 +45,7 @@ final class MessageTextView: UITextView, PillAttachmentViewProviderDelegate { struct MessageText: UIViewRepresentable { @Environment(\.openURL) private var openURLAction - @Environment(\.roomContext) private var viewModel + @Environment(\.timelineContext) private var viewModel @State private var computedSizes = [Double: CGSize]() @State var attributedString: AttributedString { @@ -66,7 +57,7 @@ struct MessageText: UIViewRepresentable { func makeUIView(context: Context) -> MessageTextView { // Need to use TextKit 1 for mentions let textView = MessageTextView(usingTextLayoutManager: false) - textView.roomContext = viewModel + textView.timelineContext = viewModel textView.updateClosure = { [weak textView] in guard let textView else { return } do { @@ -197,7 +188,7 @@ struct MessageText_Previews: PreviewProvider, TestablePreview { static var attachmentPreview: some View { MessageText(attributedString: attributedStringWithAttachment) .border(Color.purple) - .environmentObject(RoomScreenViewModel.mock.context) + .environmentObject(TimelineViewModel.mock.context) } static var previews: some View { diff --git a/ElementX/Sources/Other/Pills/PillAttachmentViewProvider.swift b/ElementX/Sources/Other/Pills/PillAttachmentViewProvider.swift index 0959e9607d..2e96579881 100644 --- a/ElementX/Sources/Other/Pills/PillAttachmentViewProvider.swift +++ b/ElementX/Sources/Other/Pills/PillAttachmentViewProvider.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -21,7 +12,7 @@ import UIKit import WysiwygComposer protocol PillAttachmentViewProviderDelegate: AnyObject { - var roomContext: RoomScreenViewModel.Context? { get } + var timelineContext: TimelineViewModel.Context? { get } func registerPillView(_ pillView: UIView) func invalidateTextAttachmentsDisplay() @@ -51,20 +42,20 @@ final class PillAttachmentViewProvider: NSTextAttachmentViewProvider, NSSecureCo } let context: PillContext - let imageProvider: ImageProviderProtocol? + let mediaProvider: MediaProviderProtocol? if ProcessInfo.isXcodePreview || ProcessInfo.isRunningTests { // The mock viewModel simulates the loading logic for testing purposes context = PillContext.mock(type: .loadUser(isOwn: false)) - imageProvider = MockMediaProvider() - } else if let roomContext = delegate?.roomContext { - context = PillContext(roomContext: roomContext, data: pillData) - imageProvider = roomContext.imageProvider + mediaProvider = MockMediaProvider() + } else if let timelineContext = delegate?.timelineContext { + context = PillContext(timelineContext: timelineContext, data: pillData) + mediaProvider = timelineContext.mediaProvider } else { MXLog.failure("[PillAttachmentViewProvider]: missing room context") return } - let view = PillView(imageProvider: imageProvider, context: context) { [weak self] in + let view = PillView(mediaProvider: mediaProvider, context: context) { [weak self] in self?.delegate?.invalidateTextAttachmentsDisplay() } let controller = UIHostingController(rootView: view) @@ -93,21 +84,21 @@ final class PillAttachmentViewProvider: NSTextAttachmentViewProvider, NSSecureCo } final class ComposerMentionDisplayHelper: MentionDisplayHelper { - weak var roomContext: RoomScreenViewModel.Context? + weak var timelineContext: TimelineViewModel.Context? - init(roomContext: RoomScreenViewModel.Context) { - self.roomContext = roomContext + init(timelineContext: TimelineViewModel.Context) { + self.timelineContext = timelineContext } @MainActor static var mock: Self { - Self(roomContext: RoomScreenViewModel.mock.context) + Self(timelineContext: TimelineViewModel.mock.context) } } extension WysiwygTextView: PillAttachmentViewProviderDelegate { - var roomContext: RoomScreenViewModel.Context? { - (mentionDisplayHelper as? ComposerMentionDisplayHelper)?.roomContext + var timelineContext: TimelineViewModel.Context? { + (mentionDisplayHelper as? ComposerMentionDisplayHelper)?.timelineContext } func invalidateTextAttachmentsDisplay() { } diff --git a/ElementX/Sources/Other/Pills/PillConstants.swift b/ElementX/Sources/Other/Pills/PillConstants.swift index 4f1784c8d8..4a62cb1f89 100644 --- a/ElementX/Sources/Other/Pills/PillConstants.swift +++ b/ElementX/Sources/Other/Pills/PillConstants.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Pills/PillContext.swift b/ElementX/Sources/Other/Pills/PillContext.swift index 49a1a618f3..f588a91fce 100644 --- a/ElementX/Sources/Other/Pills/PillContext.swift +++ b/ElementX/Sources/Other/Pills/PillContext.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -28,11 +19,11 @@ final class PillContext: ObservableObject { private var cancellable: AnyCancellable? - init(roomContext: RoomScreenViewModel.Context, data: PillTextAttachmentData) { + init(timelineContext: TimelineViewModel.Context, data: PillTextAttachmentData) { switch data.type { case let .user(id): - let isOwnMention = id == roomContext.viewState.ownUserID - if let profile = roomContext.viewState.members[id] { + let isOwnMention = id == timelineContext.viewState.ownUserID + if let profile = timelineContext.viewState.members[id] { var name = id if let displayName = profile.displayName { name = "@\(displayName)" @@ -40,7 +31,7 @@ final class PillContext: ObservableObject { viewState = PillViewState(isOwnMention: isOwnMention, displayText: name) } else { viewState = PillViewState(isOwnMention: isOwnMention, displayText: id) - cancellable = roomContext.$viewState.sink { [weak self] viewState in + cancellable = timelineContext.$viewState.sink { [weak self] viewState in guard let self else { return } @@ -73,7 +64,7 @@ extension PillContext { switch type { case .loadUser(let isOwn): pillType = .user(userID: testID) - let viewModel = PillContext(roomContext: RoomScreenViewModel.mock.context, data: PillTextAttachmentData(type: pillType, font: .preferredFont(forTextStyle: .body))) + let viewModel = PillContext(timelineContext: TimelineViewModel.mock.context, data: PillTextAttachmentData(type: pillType, font: .preferredFont(forTextStyle: .body))) viewModel.viewState = PillViewState(isOwnMention: isOwn, displayText: testID) Task { try? await Task.sleep(for: .seconds(2)) @@ -82,12 +73,12 @@ extension PillContext { return viewModel case .loadedUser(let isOwn): pillType = .user(userID: "@test:test.com") - let viewModel = PillContext(roomContext: RoomScreenViewModel.mock.context, data: PillTextAttachmentData(type: pillType, font: .preferredFont(forTextStyle: .body))) + let viewModel = PillContext(timelineContext: TimelineViewModel.mock.context, data: PillTextAttachmentData(type: pillType, font: .preferredFont(forTextStyle: .body))) viewModel.viewState = PillViewState(isOwnMention: isOwn, displayText: "@Very Very Long Test Display Text") return viewModel case .allUsers: pillType = .allUsers - return PillContext(roomContext: RoomScreenViewModel.mock.context, data: PillTextAttachmentData(type: pillType, font: .preferredFont(forTextStyle: .body))) + return PillContext(timelineContext: TimelineViewModel.mock.context, data: PillTextAttachmentData(type: pillType, font: .preferredFont(forTextStyle: .body))) } } } diff --git a/ElementX/Sources/Other/Pills/PillTextAttachment.swift b/ElementX/Sources/Other/Pills/PillTextAttachment.swift index 6ef49d6cf1..8cb31d3daa 100644 --- a/ElementX/Sources/Other/Pills/PillTextAttachment.swift +++ b/ElementX/Sources/Other/Pills/PillTextAttachment.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UIKit diff --git a/ElementX/Sources/Other/Pills/PillTextAttachmentData.swift b/ElementX/Sources/Other/Pills/PillTextAttachmentData.swift index 2c87e941e9..2ee97922f2 100644 --- a/ElementX/Sources/Other/Pills/PillTextAttachmentData.swift +++ b/ElementX/Sources/Other/Pills/PillTextAttachmentData.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Pills/PillView.swift b/ElementX/Sources/Other/Pills/PillView.swift index a846f7f4a9..91265de629 100644 --- a/ElementX/Sources/Other/Pills/PillView.swift +++ b/ElementX/Sources/Other/Pills/PillView.swift @@ -1,23 +1,14 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI struct PillView: View { - let imageProvider: ImageProviderProtocol? + let mediaProvider: MediaProviderProtocol? @ObservedObject var context: PillContext /// callback triggerd by changes in the display text let didChangeText: () -> Void @@ -49,23 +40,23 @@ struct PillView_Previews: PreviewProvider, TestablePreview { static let mockMediaProvider = MockMediaProvider() static var previews: some View { - PillView(imageProvider: mockMediaProvider, + PillView(mediaProvider: mockMediaProvider, context: PillContext.mock(type: .loadUser(isOwn: false))) { } .frame(maxWidth: PillConstants.mockMaxWidth) .previewDisplayName("Loading") - PillView(imageProvider: mockMediaProvider, + PillView(mediaProvider: mockMediaProvider, context: PillContext.mock(type: .loadUser(isOwn: true))) { } .frame(maxWidth: PillConstants.mockMaxWidth) .previewDisplayName("Loading Own") - PillView(imageProvider: mockMediaProvider, + PillView(mediaProvider: mockMediaProvider, context: PillContext.mock(type: .loadedUser(isOwn: false))) { } .frame(maxWidth: PillConstants.mockMaxWidth) .previewDisplayName("Loaded Long") - PillView(imageProvider: mockMediaProvider, + PillView(mediaProvider: mockMediaProvider, context: PillContext.mock(type: .loadedUser(isOwn: true))) { } .frame(maxWidth: PillConstants.mockMaxWidth) .previewDisplayName("Loaded Long Own") - PillView(imageProvider: mockMediaProvider, + PillView(mediaProvider: mockMediaProvider, context: PillContext.mock(type: .allUsers)) { } .frame(maxWidth: PillConstants.mockMaxWidth) .previewDisplayName("All Users") diff --git a/ElementX/Sources/Other/Pills/PlainMentionBuilder.swift b/ElementX/Sources/Other/Pills/PlainMentionBuilder.swift index f47b253a7d..7956f9e248 100644 --- a/ElementX/Sources/Other/Pills/PlainMentionBuilder.swift +++ b/ElementX/Sources/Other/Pills/PlainMentionBuilder.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/ProcessInfo.swift b/ElementX/Sources/Other/ProcessInfo.swift index d41b811443..6e018dad05 100644 --- a/ElementX/Sources/Other/ProcessInfo.swift +++ b/ElementX/Sources/Other/ProcessInfo.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/Progress/ProgressCursorModifier.swift b/ElementX/Sources/Other/Progress/ProgressCursorModifier.swift index 63a359861c..eac470112e 100644 --- a/ElementX/Sources/Other/Progress/ProgressCursorModifier.swift +++ b/ElementX/Sources/Other/Progress/ProgressCursorModifier.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Other/Progress/ProgressMaskModifier.swift b/ElementX/Sources/Other/Progress/ProgressMaskModifier.swift index 8291c1a6e6..b36c25869a 100644 --- a/ElementX/Sources/Other/Progress/ProgressMaskModifier.swift +++ b/ElementX/Sources/Other/Progress/ProgressMaskModifier.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/ScrollViewAdapter.swift b/ElementX/Sources/Other/ScrollViewAdapter.swift index acc37263e7..37907090d6 100644 --- a/ElementX/Sources/Other/ScrollViewAdapter.swift +++ b/ElementX/Sources/Other/ScrollViewAdapter.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Other/ShareToMapsAppActivity.swift b/ElementX/Sources/Other/ShareToMapsAppActivity.swift index 937ae218c0..74415592fa 100644 --- a/ElementX/Sources/Other/ShareToMapsAppActivity.swift +++ b/ElementX/Sources/Other/ShareToMapsAppActivity.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import CoreLocation diff --git a/ElementX/Sources/Other/SwiftUI/Animation/ElementAnimations.swift b/ElementX/Sources/Other/SwiftUI/Animation/ElementAnimations.swift index d53baefe82..c52be6247c 100644 --- a/ElementX/Sources/Other/SwiftUI/Animation/ElementAnimations.swift +++ b/ElementX/Sources/Other/SwiftUI/Animation/ElementAnimations.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/SwiftUI/Animation/ShimmerModifier.swift b/ElementX/Sources/Other/SwiftUI/Animation/ShimmerModifier.swift index 3fb38e371c..bbe17e5bb7 100644 --- a/ElementX/Sources/Other/SwiftUI/Animation/ShimmerModifier.swift +++ b/ElementX/Sources/Other/SwiftUI/Animation/ShimmerModifier.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Other/SwiftUI/Layout/CustomLayoutLabelStyle.swift b/ElementX/Sources/Other/SwiftUI/Layout/CustomLayoutLabelStyle.swift index 610e6f781c..683a610d51 100644 --- a/ElementX/Sources/Other/SwiftUI/Layout/CustomLayoutLabelStyle.swift +++ b/ElementX/Sources/Other/SwiftUI/Layout/CustomLayoutLabelStyle.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/SwiftUI/Layout/FullscreenDialog.swift b/ElementX/Sources/Other/SwiftUI/Layout/FullscreenDialog.swift index 788a1d9bcd..c026efb677 100644 --- a/ElementX/Sources/Other/SwiftUI/Layout/FullscreenDialog.swift +++ b/ElementX/Sources/Other/SwiftUI/Layout/FullscreenDialog.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/SwiftUI/Layout/MenuSheetLabelStyle.swift b/ElementX/Sources/Other/SwiftUI/Layout/MenuSheetLabelStyle.swift index 9db82b9231..0ea17f68e4 100644 --- a/ElementX/Sources/Other/SwiftUI/Layout/MenuSheetLabelStyle.swift +++ b/ElementX/Sources/Other/SwiftUI/Layout/MenuSheetLabelStyle.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/SwiftUI/Layout/ReadableFrameModifier.swift b/ElementX/Sources/Other/SwiftUI/Layout/ReadableFrameModifier.swift index 257431e35c..9d430a6d14 100644 --- a/ElementX/Sources/Other/SwiftUI/Layout/ReadableFrameModifier.swift +++ b/ElementX/Sources/Other/SwiftUI/Layout/ReadableFrameModifier.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/SwiftUI/Layout/ScaledFrameModifier.swift b/ElementX/Sources/Other/SwiftUI/Layout/ScaledFrameModifier.swift index aeb3347c43..84de64af9b 100644 --- a/ElementX/Sources/Other/SwiftUI/Layout/ScaledFrameModifier.swift +++ b/ElementX/Sources/Other/SwiftUI/Layout/ScaledFrameModifier.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/SwiftUI/Layout/ScaledOffsetModifier.swift b/ElementX/Sources/Other/SwiftUI/Layout/ScaledOffsetModifier.swift index 2b3d249fa1..550e470f4b 100644 --- a/ElementX/Sources/Other/SwiftUI/Layout/ScaledOffsetModifier.swift +++ b/ElementX/Sources/Other/SwiftUI/Layout/ScaledOffsetModifier.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/SwiftUI/Layout/ScaledPaddingModifier.swift b/ElementX/Sources/Other/SwiftUI/Layout/ScaledPaddingModifier.swift index 6faf800f56..c2e5e86136 100644 --- a/ElementX/Sources/Other/SwiftUI/Layout/ScaledPaddingModifier.swift +++ b/ElementX/Sources/Other/SwiftUI/Layout/ScaledPaddingModifier.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/SwiftUI/Layout/TimelineMediaFrame.swift b/ElementX/Sources/Other/SwiftUI/Layout/TimelineMediaFrame.swift index a5d7092619..1cec148401 100644 --- a/ElementX/Sources/Other/SwiftUI/Layout/TimelineMediaFrame.swift +++ b/ElementX/Sources/Other/SwiftUI/Layout/TimelineMediaFrame.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -20,6 +11,7 @@ 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 { + let defaultMediaSize = 100.0 let minMediaHeight = 100.0 let maxMediaHeight = 300.0 @@ -32,9 +24,8 @@ extension View { .frame(maxHeight: min(maxMediaHeight, max(minMediaHeight, contentHeight ?? .infinity))) // Required to prevent the reply details to get higher priority in rendering the width of the view. .aspectRatio(contentAspectRatio, contentMode: .fit) - } else { // Otherwise let the image load and use its native aspect ratio with a max height - aspectRatio(contentMode: .fit) - .frame(maxHeight: maxMediaHeight) + } else { // Otherwise force the image to be `defaultMediaSize` x `defaultMediaSize` + frame(width: defaultMediaSize, height: defaultMediaSize) } } } diff --git a/ElementX/Sources/Other/SwiftUI/Layout/ViewFrameReader.swift b/ElementX/Sources/Other/SwiftUI/Layout/ViewFrameReader.swift index 7907e46bef..a9afd39d0b 100644 --- a/ElementX/Sources/Other/SwiftUI/Layout/ViewFrameReader.swift +++ b/ElementX/Sources/Other/SwiftUI/Layout/ViewFrameReader.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/SwiftUI/Search.swift b/ElementX/Sources/Other/SwiftUI/Search.swift index 50e3b6acb8..e9ba319837 100644 --- a/ElementX/Sources/Other/SwiftUI/Search.swift +++ b/ElementX/Sources/Other/SwiftUI/Search.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/SwiftUI/Styles/FormButtonStyles.swift b/ElementX/Sources/Other/SwiftUI/Styles/FormButtonStyles.swift index 61cbe0fc78..75e952a580 100644 --- a/ElementX/Sources/Other/SwiftUI/Styles/FormButtonStyles.swift +++ b/ElementX/Sources/Other/SwiftUI/Styles/FormButtonStyles.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Other/SwiftUI/ViewModel/BindableState.swift b/ElementX/Sources/Other/SwiftUI/ViewModel/BindableState.swift index 15d67d2c58..b1854edf35 100644 --- a/ElementX/Sources/Other/SwiftUI/ViewModel/BindableState.swift +++ b/ElementX/Sources/Other/SwiftUI/ViewModel/BindableState.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/SwiftUI/ViewModel/StateStoreViewModel.swift b/ElementX/Sources/Other/SwiftUI/ViewModel/StateStoreViewModel.swift index 861f9a55fa..ce33e685b4 100644 --- a/ElementX/Sources/Other/SwiftUI/ViewModel/StateStoreViewModel.swift +++ b/ElementX/Sources/Other/SwiftUI/ViewModel/StateStoreViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -38,8 +29,8 @@ class StateStoreViewModel { set { context.viewState = newValue } } - init(initialViewState: State, imageProvider: ImageProviderProtocol? = nil) { - context = Context(initialViewState: initialViewState, imageProvider: imageProvider) + init(initialViewState: State, mediaProvider: MediaProviderProtocol? = nil) { + context = Context(initialViewState: initialViewState, mediaProvider: mediaProvider) context.viewModel = self } @@ -73,7 +64,7 @@ class StateStoreViewModel { /// An optional image loading service so that views can manage themselves /// Intentionally non-generic so that it doesn't grow uncontrollably - let imageProvider: ImageProviderProtocol? + let mediaProvider: MediaProviderProtocol? /// Set-able/Bindable access to the bindable state. subscript(dynamicMember keyPath: WritableKeyPath) -> T { @@ -87,9 +78,9 @@ class StateStoreViewModel { viewModel?.process(viewAction: viewAction) } - fileprivate init(initialViewState: State, imageProvider: ImageProviderProtocol?) { + fileprivate init(initialViewState: State, mediaProvider: MediaProviderProtocol?) { self.viewState = initialViewState - self.imageProvider = imageProvider + self.mediaProvider = mediaProvider } } } diff --git a/ElementX/Sources/Other/SwiftUI/Views/AppActivityView.swift b/ElementX/Sources/Other/SwiftUI/Views/AppActivityView.swift index 69aa78b117..2de0c8887c 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/AppActivityView.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/AppActivityView.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/SwiftUI/Views/AvatarHeaderView.swift b/ElementX/Sources/Other/SwiftUI/Views/AvatarHeaderView.swift index 47ecc63563..4b63f20cae 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/AvatarHeaderView.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/AvatarHeaderView.swift @@ -1,19 +1,11 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // +import Compound import SwiftUI struct AvatarHeaderView: View { @@ -33,13 +25,13 @@ struct AvatarHeaderView: View { private let badges: [Badge] private let avatarSize: AvatarSize - private let imageProvider: ImageProviderProtocol? + private let mediaProvider: MediaProviderProtocol? private var onAvatarTap: (() -> Void)? @ViewBuilder private var footer: () -> Footer init(room: RoomDetails, avatarSize: AvatarSize, - imageProvider: ImageProviderProtocol? = nil, + mediaProvider: MediaProviderProtocol? = nil, onAvatarTap: (() -> Void)? = nil, @ViewBuilder footer: @escaping () -> Footer) { avatarInfo = .room(room.avatar) @@ -47,7 +39,7 @@ struct AvatarHeaderView: View { subtitle = room.canonicalAlias self.avatarSize = avatarSize - self.imageProvider = imageProvider + self.mediaProvider = mediaProvider self.onAvatarTap = onAvatarTap self.footer = footer @@ -61,7 +53,7 @@ struct AvatarHeaderView: View { init(accountOwner: RoomMemberDetails, dmRecipient: RoomMemberDetails, - imageProvider: ImageProviderProtocol? = nil, + mediaProvider: MediaProviderProtocol? = nil, onAvatarTap: (() -> Void)? = nil, @ViewBuilder footer: @escaping () -> Footer) { let dmRecipientProfile = UserProfileProxy(member: dmRecipient) @@ -70,7 +62,7 @@ struct AvatarHeaderView: View { subtitle = dmRecipientProfile.displayName == nil ? nil : dmRecipientProfile.userID avatarSize = .user(on: .dmDetails) - self.imageProvider = imageProvider + self.mediaProvider = mediaProvider self.onAvatarTap = onAvatarTap self.footer = footer // In EL-X a DM is by definition always encrypted @@ -79,21 +71,21 @@ struct AvatarHeaderView: View { init(member: RoomMemberDetails, avatarSize: AvatarSize, - imageProvider: ImageProviderProtocol? = nil, + mediaProvider: MediaProviderProtocol? = nil, onAvatarTap: (() -> Void)? = nil, @ViewBuilder footer: @escaping () -> Footer) { let profile = UserProfileProxy(member: member) self.init(user: profile, avatarSize: avatarSize, - imageProvider: imageProvider, + mediaProvider: mediaProvider, onAvatarTap: onAvatarTap, footer: footer) } init(user: UserProfileProxy, avatarSize: AvatarSize, - imageProvider: ImageProviderProtocol? = nil, + mediaProvider: MediaProviderProtocol? = nil, onAvatarTap: (() -> Void)? = nil, @ViewBuilder footer: @escaping () -> Footer) { avatarInfo = .user(user) @@ -101,7 +93,7 @@ struct AvatarHeaderView: View { subtitle = user.displayName == nil ? nil : user.userID self.avatarSize = avatarSize - self.imageProvider = imageProvider + self.mediaProvider = mediaProvider self.onAvatarTap = onAvatarTap self.footer = footer badges = [] @@ -136,13 +128,13 @@ struct AvatarHeaderView: View { case .room(let roomAvatar): RoomAvatarImage(avatar: roomAvatar, avatarSize: avatarSize, - imageProvider: imageProvider) + mediaProvider: mediaProvider) case .user(let userProfile): LoadableAvatarImage(url: userProfile.avatarURL, name: userProfile.displayName, contentID: userProfile.userID, avatarSize: avatarSize, - imageProvider: imageProvider) + mediaProvider: mediaProvider) } } @@ -199,10 +191,10 @@ struct AvatarHeaderView_Previews: PreviewProvider, TestablePreview { isEncrypted: true, isPublic: true), avatarSize: .room(on: .details), - imageProvider: MockMediaProvider()) { + mediaProvider: MockMediaProvider()) { HStack(spacing: 32) { ShareLink(item: "test") { - Image(systemName: "square.and.arrow.up") + CompoundIcon(\.shareIos) } .buttonStyle(FormActionButtonStyle(title: "Test")) } @@ -213,10 +205,10 @@ struct AvatarHeaderView_Previews: PreviewProvider, TestablePreview { Form { AvatarHeaderView(accountOwner: RoomMemberDetails(withProxy: RoomMemberProxyMock.mockMe), dmRecipient: RoomMemberDetails(withProxy: RoomMemberProxyMock.mockAlice), - imageProvider: MockMediaProvider()) { + mediaProvider: MockMediaProvider()) { HStack(spacing: 32) { ShareLink(item: "test") { - Image(systemName: "square.and.arrow.up") + CompoundIcon(\.shareIos) } .buttonStyle(FormActionButtonStyle(title: "Test")) } @@ -228,11 +220,11 @@ struct AvatarHeaderView_Previews: PreviewProvider, TestablePreview { VStack(spacing: 16) { AvatarHeaderView(member: RoomMemberDetails(withProxy: RoomMemberProxyMock.mockAlice), avatarSize: .room(on: .details), - imageProvider: MockMediaProvider()) { Text("") } + mediaProvider: MockMediaProvider()) { Text("") } AvatarHeaderView(member: RoomMemberDetails(withProxy: RoomMemberProxyMock.mockBanned[3]), avatarSize: .room(on: .details), - imageProvider: MockMediaProvider()) { Text("") } + mediaProvider: MockMediaProvider()) { Text("") } } .padding() .background(Color.compound.bgSubtleSecondaryLevel0) diff --git a/ElementX/Sources/Other/SwiftUI/Views/BadgeLabel.swift b/ElementX/Sources/Other/SwiftUI/Views/BadgeLabel.swift index e50ace1251..4faf88646a 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/BadgeLabel.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/BadgeLabel.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Other/SwiftUI/Views/BadgeView.swift b/ElementX/Sources/Other/SwiftUI/Views/BadgeView.swift index 4dc76184dd..553ddce491 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/BadgeView.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/BadgeView.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Other/SwiftUI/Views/ButtonStyle.swift b/ElementX/Sources/Other/SwiftUI/Views/ButtonStyle.swift index 3bc36ff9c9..a703d7ba1a 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/ButtonStyle.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/ButtonStyle.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/SwiftUI/Views/HeroImage.swift b/ElementX/Sources/Other/SwiftUI/Views/HeroImage.swift index c2bdd3b655..f50ecb11e3 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/HeroImage.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/HeroImage.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -23,33 +14,36 @@ import SwiftUI struct HeroImage: View { enum Style { case normal - case positive case subtle + case success case critical + case criticalOnSecondary var foregroundColor: Color { switch self { case .normal: - return .compound.iconPrimary - case .positive: - return .compound.iconSuccessPrimary + .compound.iconPrimary case .subtle: - return .compound.iconSecondary - case .critical: - return .compound.iconCriticalPrimary + .compound.iconSecondary + case .success: + .compound.iconSuccessPrimary + case .critical, .criticalOnSecondary: + .compound.iconCriticalPrimary } } var backgroundFillColor: Color { switch self { case .normal: - return .compound.bgSubtleSecondary - case .positive: - return .compound.bgSuccessSubtle + .compound.bgSubtleSecondary case .subtle: - return .compound.bgSubtlePrimary + .compound.bgSubtlePrimary + case .success: + .compound.bgSuccessSubtle case .critical: - return .compound.bgCanvasDefault + .compound.bgCriticalSubtle + case .criticalOnSecondary: + .compound.bgCanvasDefault } } } @@ -95,12 +89,21 @@ private struct HeroImageModifier: ViewModifier { struct HeroImage_Previews: PreviewProvider, TestablePreview { static var previews: some View { - HStack(spacing: 20) { - HeroImage(icon: \.lockSolid) - Image(systemName: "hourglass") - .heroImage() - Image(asset: Asset.Images.serverSelectionIcon) - .heroImage(insets: 19) + VStack(spacing: 20) { + HStack(spacing: 20) { + HeroImage(icon: \.lockSolid) + Image(systemName: "hourglass") + .heroImage() + Image(asset: Asset.Images.serverSelectionIcon) + .heroImage(insets: 19) + } + + HStack(spacing: 20) { + HeroImage(icon: \.helpSolid, style: .subtle) + HeroImage(icon: \.checkCircleSolid, style: .success) + HeroImage(icon: \.error, style: .critical) + HeroImage(icon: \.error, style: .criticalOnSecondary) + } } } } diff --git a/ElementX/Sources/Other/SwiftUI/Views/LoadableAvatarImage.swift b/ElementX/Sources/Other/SwiftUI/Views/LoadableAvatarImage.swift index 06d4972fed..f311b321f8 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/LoadableAvatarImage.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/LoadableAvatarImage.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -21,16 +12,16 @@ struct LoadableAvatarImage: View { private let name: String? private let contentID: String? private let avatarSize: AvatarSize - private let imageProvider: ImageProviderProtocol? + private let mediaProvider: MediaProviderProtocol? @ScaledMetric private var frameSize: CGFloat - init(url: URL?, name: String?, contentID: String?, avatarSize: AvatarSize, imageProvider: ImageProviderProtocol?) { + init(url: URL?, name: String?, contentID: String?, avatarSize: AvatarSize, mediaProvider: MediaProviderProtocol?) { self.url = url self.name = name self.contentID = contentID self.avatarSize = avatarSize - self.imageProvider = imageProvider + self.mediaProvider = mediaProvider _frameSize = ScaledMetric(wrappedValue: avatarSize.value) } @@ -48,7 +39,7 @@ struct LoadableAvatarImage: View { LoadableImage(url: url, mediaType: .avatar, size: avatarSize.scaledSize, - imageProvider: imageProvider) { image in + mediaProvider: mediaProvider) { image in image .scaledToFill() } placeholder: { diff --git a/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift b/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift index 7ae8f09bc4..d1183ca400 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift @@ -1,19 +1,11 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // +import Combine import Kingfisher import SwiftUI @@ -28,7 +20,7 @@ struct LoadableImage: View { private let mediaType: LoadableImageMediaType private let blurhash: String? private let size: CGSize? - private let imageProvider: ImageProviderProtocol? + private let mediaProvider: MediaProviderProtocol? private let transformer: (AnyView) -> TransformerView private let placeholder: () -> PlaceholderView @@ -44,14 +36,14 @@ struct LoadableImage: View { mediaType: LoadableImageMediaType = .generic, blurhash: String? = nil, size: CGSize? = nil, - imageProvider: ImageProviderProtocol?, + mediaProvider: MediaProviderProtocol?, transformer: @escaping (AnyView) -> TransformerView = { $0 }, placeholder: @escaping () -> PlaceholderView) { self.mediaSource = mediaSource self.mediaType = mediaType self.blurhash = blurhash self.size = size - self.imageProvider = imageProvider + self.mediaProvider = mediaProvider self.transformer = transformer self.placeholder = placeholder } @@ -60,14 +52,14 @@ struct LoadableImage: View { mediaType: LoadableImageMediaType = .generic, blurhash: String? = nil, size: CGSize? = nil, - imageProvider: ImageProviderProtocol?, + mediaProvider: MediaProviderProtocol?, transformer: @escaping (AnyView) -> TransformerView = { $0 }, placeholder: @escaping () -> PlaceholderView) { self.init(mediaSource: MediaSourceProxy(url: url, mimeType: nil), mediaType: mediaType, blurhash: blurhash, size: size, - imageProvider: imageProvider, + mediaProvider: mediaProvider, transformer: transformer, placeholder: placeholder) } @@ -77,7 +69,7 @@ struct LoadableImage: View { mediaType: mediaType, blurhash: blurhash, size: size, - imageProvider: imageProvider, + mediaProvider: mediaProvider, transformer: transformer, placeholder: placeholder) // Binds the lifecycle of the LoadableImage to the associated URL. @@ -99,20 +91,22 @@ private struct LoadableImageContent TransformerView, placeholder: @escaping () -> PlaceholderView) { - assert(imageProvider != nil, "Missing image provider, make sure one has been supplied to the view model.") + assert(mediaProvider != nil, "Missing image provider, make sure one has been supplied to the view model.") self.mediaSource = mediaSource self.mediaType = mediaType self.blurhash = blurhash self.transformer = transformer self.placeholder = placeholder - _contentLoader = StateObject(wrappedValue: ContentLoader(mediaSource: mediaSource, size: size, imageProvider: imageProvider)) + _contentLoader = StateObject(wrappedValue: ContentLoader(mediaSource: mediaSource, size: size, mediaProvider: mediaProvider)) } var body: some View { + // Tried putting this in the body's .task but it randomly + // decides to not execute the request let _ = Task { guard contentLoader.content == nil else { return @@ -140,6 +134,13 @@ private struct LoadableImageContent: View { struct MatrixUserPermalink_Previews: PreviewProvider, TestablePreview { static var previews: some View { MatrixUserShareLink(userID: "@someone:somewhere.org") { - Label("Share", systemImage: "square.and.arrow.up") + Label("Share", icon: \.shareIos) } } } diff --git a/ElementX/Sources/Other/SwiftUI/Views/OverridableAvatarImage.swift b/ElementX/Sources/Other/SwiftUI/Views/OverridableAvatarImage.swift index 8774516861..68137fdad4 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/OverridableAvatarImage.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/OverridableAvatarImage.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -22,17 +13,17 @@ struct OverridableAvatarImage: View { private let name: String? private let contentID: String? private let avatarSize: AvatarSize - private let imageProvider: ImageProviderProtocol? + private let mediaProvider: MediaProviderProtocol? @ScaledMetric private var frameSize: CGFloat - init(overrideURL: URL?, url: URL?, name: String?, contentID: String?, avatarSize: AvatarSize, imageProvider: ImageProviderProtocol?) { + init(overrideURL: URL?, url: URL?, name: String?, contentID: String?, avatarSize: AvatarSize, mediaProvider: MediaProviderProtocol?) { self.overrideURL = overrideURL self.url = url self.name = name self.contentID = contentID self.avatarSize = avatarSize - self.imageProvider = imageProvider + self.mediaProvider = mediaProvider _frameSize = ScaledMetric(wrappedValue: avatarSize.value) } @@ -53,7 +44,7 @@ struct OverridableAvatarImage: View { name: name, contentID: contentID, avatarSize: avatarSize, - imageProvider: imageProvider) + mediaProvider: mediaProvider) } } } diff --git a/ElementX/Sources/Other/SwiftUI/Views/PlaceholderAvatarImage.swift b/ElementX/Sources/Other/SwiftUI/Views/PlaceholderAvatarImage.swift index bd4b461871..28893a9807 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/PlaceholderAvatarImage.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/PlaceholderAvatarImage.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Other/SwiftUI/Views/RoomAvatarImage.swift b/ElementX/Sources/Other/SwiftUI/Views/RoomAvatarImage.swift index 459bb2f8ad..c7f77b116f 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/RoomAvatarImage.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/RoomAvatarImage.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -32,7 +23,7 @@ struct RoomAvatarImage: View { let avatar: RoomAvatar let avatarSize: AvatarSize - let imageProvider: ImageProviderProtocol? + let mediaProvider: MediaProviderProtocol? var body: some View { switch avatar { @@ -41,7 +32,7 @@ struct RoomAvatarImage: View { name: name, contentID: id, avatarSize: avatarSize, - imageProvider: imageProvider) + mediaProvider: mediaProvider) case .heroes(let users): // We will expand upon this with more stack sizes in the future. if users.count == 0 { @@ -54,14 +45,14 @@ struct RoomAvatarImage: View { name: users[0].displayName, contentID: users[0].userID, avatarSize: avatarSize, - imageProvider: imageProvider) + mediaProvider: mediaProvider) .scaledFrame(size: clusterSize, alignment: .topTrailing) LoadableAvatarImage(url: users[1].avatarURL, name: users[1].displayName, contentID: users[1].userID, avatarSize: avatarSize, - imageProvider: imageProvider) + mediaProvider: mediaProvider) .mask { Rectangle() .fill(Color.white) @@ -83,7 +74,7 @@ struct RoomAvatarImage: View { name: users[0].displayName, contentID: users[0].userID, avatarSize: avatarSize, - imageProvider: imageProvider) + mediaProvider: mediaProvider) } } } @@ -96,30 +87,30 @@ struct RoomAvatarImage_Previews: PreviewProvider, TestablePreview { name: "Room", avatarURL: nil), avatarSize: .room(on: .home), - imageProvider: MockMediaProvider()) + mediaProvider: MockMediaProvider()) RoomAvatarImage(avatar: .room(id: "!2:server.com", name: "Room", avatarURL: .picturesDirectory), avatarSize: .room(on: .home), - imageProvider: MockMediaProvider()) + mediaProvider: MockMediaProvider()) RoomAvatarImage(avatar: .heroes([.init(userID: "@user:server.com", displayName: "User", avatarURL: nil)]), avatarSize: .room(on: .home), - imageProvider: MockMediaProvider()) + mediaProvider: MockMediaProvider()) RoomAvatarImage(avatar: .heroes([.init(userID: "@user:server.com", displayName: "User", avatarURL: .picturesDirectory)]), avatarSize: .room(on: .home), - imageProvider: MockMediaProvider()) + mediaProvider: MockMediaProvider()) RoomAvatarImage(avatar: .heroes([.init(userID: "@alice:server.com", displayName: "Alice", avatarURL: nil), .init(userID: "@bob:server.net", displayName: "Bob", avatarURL: nil)]), avatarSize: .room(on: .home), - imageProvider: MockMediaProvider()) + mediaProvider: MockMediaProvider()) } } } diff --git a/ElementX/Sources/Other/SwiftUI/Views/RoomInviterLabel.swift b/ElementX/Sources/Other/SwiftUI/Views/RoomInviterLabel.swift index 6a11dfac21..e3fa721ab1 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/RoomInviterLabel.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/RoomInviterLabel.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -48,7 +39,7 @@ struct RoomInviterDetails: Equatable { struct RoomInviterLabel: View { let inviter: RoomInviterDetails - let imageProvider: ImageProviderProtocol? + let mediaProvider: MediaProviderProtocol? var body: some View { HStack(alignment: .firstTextBaseline, spacing: 8) { @@ -56,7 +47,7 @@ struct RoomInviterLabel: View { name: inviter.displayName, contentID: inviter.id, avatarSize: .custom(16), - imageProvider: imageProvider) + mediaProvider: mediaProvider) .alignmentGuide(.firstTextBaseline) { $0[.bottom] * 0.8 } .accessibilityHidden(true) @@ -71,13 +62,13 @@ struct RoomInviterLabel_Previews: PreviewProvider, TestablePreview { static var previews: some View { VStack(spacing: 10) { RoomInviterLabel(inviter: .init(member: RoomMemberProxyMock.mockAlice), - imageProvider: MockMediaProvider()) + mediaProvider: MockMediaProvider()) RoomInviterLabel(inviter: .init(member: RoomMemberProxyMock.mockDan), - imageProvider: MockMediaProvider()) + mediaProvider: MockMediaProvider()) RoomInviterLabel(inviter: .init(member: RoomMemberProxyMock.mockNoName), - imageProvider: MockMediaProvider()) + mediaProvider: MockMediaProvider()) RoomInviterLabel(inviter: .init(member: RoomMemberProxyMock.mockCharlie), - imageProvider: MockMediaProvider()) + mediaProvider: MockMediaProvider()) .foregroundStyle(.compound.textPrimary) } .font(.compound.bodyMD) diff --git a/ElementX/Sources/Other/SwiftUI/Views/RoundedCornerShape.swift b/ElementX/Sources/Other/SwiftUI/Views/RoundedCornerShape.swift index fe7de98416..19d8d6ab31 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/RoundedCornerShape.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/RoundedCornerShape.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/SwiftUI/Views/RoundedLabelItem.swift b/ElementX/Sources/Other/SwiftUI/Views/RoundedLabelItem.swift index bd30bf088b..d13e8c0aab 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/RoundedLabelItem.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/RoundedLabelItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2021 New Vector Ltd +// Copyright 2021-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/SwiftUI/Views/SFNumberedListView.swift b/ElementX/Sources/Other/SwiftUI/Views/SFNumberedListView.swift index 588f7441e5..b3e4e36026 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/SFNumberedListView.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/SFNumberedListView.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SFSafeSymbols diff --git a/ElementX/Sources/Other/SwiftUI/Views/UserProfileListRow.swift b/ElementX/Sources/Other/SwiftUI/Views/UserProfileListRow.swift index c71278ff77..762fbce485 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/UserProfileListRow.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/UserProfileListRow.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -21,7 +12,7 @@ import SwiftUI struct UserProfileListRow: View { let user: UserProfileProxy let membership: MembershipState? - let imageProvider: ImageProviderProtocol? + let mediaProvider: MediaProviderProtocol? let kind: ListRow.Kind @@ -52,7 +43,7 @@ struct UserProfileListRow: View { name: user.displayName, contentID: user.userID, avatarSize: .user(on: .startChat), - imageProvider: imageProvider) + mediaProvider: mediaProvider) } } @@ -74,21 +65,21 @@ struct UserProfileCell_Previews: PreviewProvider, TestablePreview { static var previews: some View { Form { - UserProfileListRow(user: .mockAlice, membership: nil, imageProvider: MockMediaProvider(), + UserProfileListRow(user: .mockAlice, membership: nil, mediaProvider: MockMediaProvider(), kind: .multiSelection(isSelected: true, action: action)) - UserProfileListRow(user: .mockBob, membership: nil, imageProvider: MockMediaProvider(), + UserProfileListRow(user: .mockBob, membership: nil, mediaProvider: MockMediaProvider(), kind: .multiSelection(isSelected: false, action: action)) - UserProfileListRow(user: .mockCharlie, membership: .join, imageProvider: MockMediaProvider(), + UserProfileListRow(user: .mockCharlie, membership: .join, mediaProvider: MockMediaProvider(), kind: .multiSelection(isSelected: true, action: action)) .disabled(true) - UserProfileListRow(user: .init(userID: "@someone:matrix.org"), membership: .join, imageProvider: MockMediaProvider(), + UserProfileListRow(user: .init(userID: "@someone:matrix.org"), membership: .join, mediaProvider: MockMediaProvider(), kind: .multiSelection(isSelected: false, action: action)) .disabled(true) - UserProfileListRow(user: .init(userID: "@someone:matrix.org"), membership: nil, imageProvider: MockMediaProvider(), + UserProfileListRow(user: .init(userID: "@someone:matrix.org"), membership: nil, mediaProvider: MockMediaProvider(), kind: .multiSelection(isSelected: false, action: action)) } .compoundList() diff --git a/ElementX/Sources/Other/TestablePreview.swift b/ElementX/Sources/Other/TestablePreview.swift index e138b9cd3e..a1c766725f 100644 --- a/ElementX/Sources/Other/TestablePreview.swift +++ b/ElementX/Sources/Other/TestablePreview.swift @@ -1,21 +1,10 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI -import Prefire - -protocol TestablePreview: PrefireProvider { } +protocol TestablePreview { } diff --git a/ElementX/Sources/Other/UserAgentBuilder.swift b/ElementX/Sources/Other/UserAgentBuilder.swift index 09c56f30c2..ac5a27a131 100644 --- a/ElementX/Sources/Other/UserAgentBuilder.swift +++ b/ElementX/Sources/Other/UserAgentBuilder.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Other/UserIndicator/UserIndicator.swift b/ElementX/Sources/Other/UserIndicator/UserIndicator.swift index 8a47c8ea2b..4690a92a9e 100644 --- a/ElementX/Sources/Other/UserIndicator/UserIndicator.swift +++ b/ElementX/Sources/Other/UserIndicator/UserIndicator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Other/UserIndicator/UserIndicatorController.swift b/ElementX/Sources/Other/UserIndicator/UserIndicatorController.swift index 0406feae04..00e6eb197a 100644 --- a/ElementX/Sources/Other/UserIndicator/UserIndicatorController.swift +++ b/ElementX/Sources/Other/UserIndicator/UserIndicatorController.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/UserIndicator/UserIndicatorControllerProtocol.swift b/ElementX/Sources/Other/UserIndicator/UserIndicatorControllerProtocol.swift index 6dcf3a6c92..85dc803457 100644 --- a/ElementX/Sources/Other/UserIndicator/UserIndicatorControllerProtocol.swift +++ b/ElementX/Sources/Other/UserIndicator/UserIndicatorControllerProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UIKit diff --git a/ElementX/Sources/Other/UserIndicator/UserIndicatorModalView.swift b/ElementX/Sources/Other/UserIndicator/UserIndicatorModalView.swift index 24fc26480e..00ca273f4c 100644 --- a/ElementX/Sources/Other/UserIndicator/UserIndicatorModalView.swift +++ b/ElementX/Sources/Other/UserIndicator/UserIndicatorModalView.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Other/UserIndicator/UserIndicatorPresenter.swift b/ElementX/Sources/Other/UserIndicator/UserIndicatorPresenter.swift index 6a513a61e0..741c56e916 100644 --- a/ElementX/Sources/Other/UserIndicator/UserIndicatorPresenter.swift +++ b/ElementX/Sources/Other/UserIndicator/UserIndicatorPresenter.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/UserIndicator/UserIndicatorToastView.swift b/ElementX/Sources/Other/UserIndicator/UserIndicatorToastView.swift index d1044d8dbc..e1990716ad 100644 --- a/ElementX/Sources/Other/UserIndicator/UserIndicatorToastView.swift +++ b/ElementX/Sources/Other/UserIndicator/UserIndicatorToastView.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/UserPreference.swift b/ElementX/Sources/Other/UserPreference.swift index 8f5c8d076f..c8184b152a 100644 --- a/ElementX/Sources/Other/UserPreference.swift +++ b/ElementX/Sources/Other/UserPreference.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Other/VoiceMessage/EstimatedWaveformView.swift b/ElementX/Sources/Other/VoiceMessage/EstimatedWaveformView.swift index 49ff34eb75..c10e77fac9 100644 --- a/ElementX/Sources/Other/VoiceMessage/EstimatedWaveformView.swift +++ b/ElementX/Sources/Other/VoiceMessage/EstimatedWaveformView.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/VoiceMessage/VoiceMessageButton.swift b/ElementX/Sources/Other/VoiceMessage/VoiceMessageButton.swift index 827a5c99c5..d0fffff0f8 100644 --- a/ElementX/Sources/Other/VoiceMessage/VoiceMessageButton.swift +++ b/ElementX/Sources/Other/VoiceMessage/VoiceMessageButton.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/VoiceMessage/WaveformCursorView.swift b/ElementX/Sources/Other/VoiceMessage/WaveformCursorView.swift index 5220c1792c..a4dd30c560 100644 --- a/ElementX/Sources/Other/VoiceMessage/WaveformCursorView.swift +++ b/ElementX/Sources/Other/VoiceMessage/WaveformCursorView.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Other/VoiceMessage/WaveformInteractionModifier.swift b/ElementX/Sources/Other/VoiceMessage/WaveformInteractionModifier.swift index 16d21728a9..c3e3364bd3 100644 --- a/ElementX/Sources/Other/VoiceMessage/WaveformInteractionModifier.swift +++ b/ElementX/Sources/Other/VoiceMessage/WaveformInteractionModifier.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Other/VoiceMessage/WaveformSource.swift b/ElementX/Sources/Other/VoiceMessage/WaveformSource.swift index b3dd547f1f..15ce483e3a 100644 --- a/ElementX/Sources/Other/VoiceMessage/WaveformSource.swift +++ b/ElementX/Sources/Other/VoiceMessage/WaveformSource.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/AppLock/AppLockScreen/AppLockScreenCoordinator.swift b/ElementX/Sources/Screens/AppLock/AppLockScreen/AppLockScreenCoordinator.swift index c7b57d974c..178d4320e1 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockScreen/AppLockScreenCoordinator.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockScreen/AppLockScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/AppLock/AppLockScreen/AppLockScreenModels.swift b/ElementX/Sources/Screens/AppLock/AppLockScreen/AppLockScreenModels.swift index 225d24b9d6..e9e737057d 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockScreen/AppLockScreenModels.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockScreen/AppLockScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/AppLock/AppLockScreen/AppLockScreenViewModel.swift b/ElementX/Sources/Screens/AppLock/AppLockScreen/AppLockScreenViewModel.swift index 9b25b101a1..11897cf5a0 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockScreen/AppLockScreenViewModel.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockScreen/AppLockScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/AppLock/AppLockScreen/AppLockScreenViewModelProtocol.swift b/ElementX/Sources/Screens/AppLock/AppLockScreen/AppLockScreenViewModelProtocol.swift index 4cc2f9fa13..6a3fd8a322 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockScreen/AppLockScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockScreen/AppLockScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/AppLock/AppLockScreen/View/AppLockScreen.swift b/ElementX/Sources/Screens/AppLock/AppLockScreen/View/AppLockScreen.swift index 6bb4bc7058..f607fbdc38 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockScreen/View/AppLockScreen.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockScreen/View/AppLockScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/AppLock/AppLockScreen/View/AppLockScreenPINKeypad.swift b/ElementX/Sources/Screens/AppLock/AppLockScreen/View/AppLockScreenPINKeypad.swift index 75e40a6fce..c0a313fcfe 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockScreen/View/AppLockScreenPINKeypad.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockScreen/View/AppLockScreenPINKeypad.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/AppLock/AppLockSetupBiometricsScreen/AppLockSetupBiometricsScreenCoordinator.swift b/ElementX/Sources/Screens/AppLock/AppLockSetupBiometricsScreen/AppLockSetupBiometricsScreenCoordinator.swift index af3b4db5ef..ac971858be 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockSetupBiometricsScreen/AppLockSetupBiometricsScreenCoordinator.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockSetupBiometricsScreen/AppLockSetupBiometricsScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/AppLock/AppLockSetupBiometricsScreen/AppLockSetupBiometricsScreenModels.swift b/ElementX/Sources/Screens/AppLock/AppLockSetupBiometricsScreen/AppLockSetupBiometricsScreenModels.swift index 6f250084fb..e4ccc78a58 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockSetupBiometricsScreen/AppLockSetupBiometricsScreenModels.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockSetupBiometricsScreen/AppLockSetupBiometricsScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import LocalAuthentication diff --git a/ElementX/Sources/Screens/AppLock/AppLockSetupBiometricsScreen/AppLockSetupBiometricsScreenViewModel.swift b/ElementX/Sources/Screens/AppLock/AppLockSetupBiometricsScreen/AppLockSetupBiometricsScreenViewModel.swift index 7ec3cdfb7e..786c178172 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockSetupBiometricsScreen/AppLockSetupBiometricsScreenViewModel.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockSetupBiometricsScreen/AppLockSetupBiometricsScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/AppLock/AppLockSetupBiometricsScreen/AppLockSetupBiometricsScreenViewModelProtocol.swift b/ElementX/Sources/Screens/AppLock/AppLockSetupBiometricsScreen/AppLockSetupBiometricsScreenViewModelProtocol.swift index 0e38e53afb..42356d61ba 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockSetupBiometricsScreen/AppLockSetupBiometricsScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockSetupBiometricsScreen/AppLockSetupBiometricsScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/AppLock/AppLockSetupBiometricsScreen/View/AppLockSetupBiometricsScreen.swift b/ElementX/Sources/Screens/AppLock/AppLockSetupBiometricsScreen/View/AppLockSetupBiometricsScreen.swift index 11afc62364..26756b72bf 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockSetupBiometricsScreen/View/AppLockSetupBiometricsScreen.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockSetupBiometricsScreen/View/AppLockSetupBiometricsScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/AppLockSetupPINScreenCoordinator.swift b/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/AppLockSetupPINScreenCoordinator.swift index 555420c4dd..aba59737b6 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/AppLockSetupPINScreenCoordinator.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/AppLockSetupPINScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/AppLockSetupPINScreenModels.swift b/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/AppLockSetupPINScreenModels.swift index 7c1a54af9e..2476cde33d 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/AppLockSetupPINScreenModels.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/AppLockSetupPINScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/AppLockSetupPINScreenViewModel.swift b/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/AppLockSetupPINScreenViewModel.swift index 8dd4023364..37021d2e2c 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/AppLockSetupPINScreenViewModel.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/AppLockSetupPINScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/AppLockSetupPINScreenViewModelProtocol.swift b/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/AppLockSetupPINScreenViewModelProtocol.swift index 2c3dfc62c8..24188a783a 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/AppLockSetupPINScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/AppLockSetupPINScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/View/AppLockSetupPINScreen.swift b/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/View/AppLockSetupPINScreen.swift index 1bb58c6a48..95a93f289b 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/View/AppLockSetupPINScreen.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/View/AppLockSetupPINScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/View/PINTextField.swift b/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/View/PINTextField.swift index aa0b172fe4..09f10d3655 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/View/PINTextField.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/View/PINTextField.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/AppLock/AppLockSetupSettingsScreen/AppLockSetupSettingsScreenCoordinator.swift b/ElementX/Sources/Screens/AppLock/AppLockSetupSettingsScreen/AppLockSetupSettingsScreenCoordinator.swift index 1710676813..a8b5ddffb8 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockSetupSettingsScreen/AppLockSetupSettingsScreenCoordinator.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockSetupSettingsScreen/AppLockSetupSettingsScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/AppLock/AppLockSetupSettingsScreen/AppLockSetupSettingsScreenModels.swift b/ElementX/Sources/Screens/AppLock/AppLockSetupSettingsScreen/AppLockSetupSettingsScreenModels.swift index 064588d0e9..72f5cfcc72 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockSetupSettingsScreen/AppLockSetupSettingsScreenModels.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockSetupSettingsScreen/AppLockSetupSettingsScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/AppLock/AppLockSetupSettingsScreen/AppLockSetupSettingsScreenViewModel.swift b/ElementX/Sources/Screens/AppLock/AppLockSetupSettingsScreen/AppLockSetupSettingsScreenViewModel.swift index 561a04ebdc..ea109b3fda 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockSetupSettingsScreen/AppLockSetupSettingsScreenViewModel.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockSetupSettingsScreen/AppLockSetupSettingsScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/AppLock/AppLockSetupSettingsScreen/AppLockSetupSettingsScreenViewModelProtocol.swift b/ElementX/Sources/Screens/AppLock/AppLockSetupSettingsScreen/AppLockSetupSettingsScreenViewModelProtocol.swift index 12e554df94..3bb9bf82a4 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockSetupSettingsScreen/AppLockSetupSettingsScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockSetupSettingsScreen/AppLockSetupSettingsScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/AppLock/AppLockSetupSettingsScreen/View/AppLockSetupSettingsScreen.swift b/ElementX/Sources/Screens/AppLock/AppLockSetupSettingsScreen/View/AppLockSetupSettingsScreen.swift index c9991edeaa..097b27079c 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockSetupSettingsScreen/View/AppLockSetupSettingsScreen.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockSetupSettingsScreen/View/AppLockSetupSettingsScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/AppLock/Common/LABiometryType.swift b/ElementX/Sources/Screens/AppLock/Common/LABiometryType.swift index 35cb788809..fd1e602fee 100644 --- a/ElementX/Sources/Screens/AppLock/Common/LABiometryType.swift +++ b/ElementX/Sources/Screens/AppLock/Common/LABiometryType.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import LocalAuthentication diff --git a/ElementX/Sources/Screens/Authentication/AuthenticationTextFieldStyle.swift b/ElementX/Sources/Screens/Authentication/AuthenticationTextFieldStyle.swift index fcdd1089c5..1255344931 100644 --- a/ElementX/Sources/Screens/Authentication/AuthenticationTextFieldStyle.swift +++ b/ElementX/Sources/Screens/Authentication/AuthenticationTextFieldStyle.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginHomeserver.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginHomeserver.swift index c2d58c7dd4..5bfb33da79 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginHomeserver.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginHomeserver.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -22,13 +13,16 @@ struct LoginHomeserver: Equatable { let address: String /// The types login supported by the homeserver. var loginMode: LoginMode + /// A temporary helper URL that can be used for registration. + var registrationHelperURL: URL? /// Creates a new homeserver value. - init(address: String, loginMode: LoginMode) { + init(address: String, loginMode: LoginMode, registrationHelperURL: URL? = nil) { let address = Self.sanitized(address).components(separatedBy: "://").last ?? address self.address = address self.loginMode = loginMode + self.registrationHelperURL = registrationHelperURL } /// Sanitizes a user entered homeserver address with the following rules @@ -54,7 +48,7 @@ struct LoginHomeserver: Equatable { extension LoginHomeserver { /// A mock homeserver that is configured just like matrix.org. static var mockMatrixDotOrg: LoginHomeserver { - LoginHomeserver(address: "matrix.org", loginMode: .password) + LoginHomeserver(address: "matrix.org", loginMode: .password, registrationHelperURL: "https://develop.element.io/#/mobile_register") } /// A mock homeserver that supports login and registration via a password but has no SSO providers. diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginMode.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginMode.swift index 3ca43cf050..775b7eedc4 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginMode.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginMode.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenCoordinator.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenCoordinator.swift index 02446f4e3a..9c6d3e2be4 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -30,10 +21,9 @@ enum LoginScreenCoordinatorAction { case configuredForOIDC /// Login was successful. case signedIn(UserSessionProtocol) - /// The user's request to login failed due to being on the proxy waitlist. - case isOnWaitlist(WaitlistScreenCredentials) } +// Note: This code was brought over from Riot, we should move the authentication service logic into the view model. final class LoginScreenCoordinator: CoordinatorProtocol { private let parameters: LoginScreenCoordinatorParameters private var viewModel: LoginScreenViewModelProtocol @@ -141,16 +131,7 @@ final class LoginScreenCoordinator: CoordinatorProtocol { case .failure(let error): stopLoading() parameters.analytics.signpost.endLogin() - switch error { - case .isOnWaitlist: - actionsSubject.send(.isOnWaitlist(.init(username: username, - password: password, - initialDeviceName: UIDevice.current.initialDeviceName, - deviceID: nil, - homeserver: authenticationService.homeserver.value))) - default: - handleError(error) - } + handleError(error) } } } diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenModels.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenModels.swift index b10dade64f..e9c80169aa 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenModels.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenViewModel.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenViewModel.swift index b2f1401366..0c81c9e412 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenViewModel.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenViewModelProtocol.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenViewModelProtocol.swift index b2473586c6..303c6151c9 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift index f4d9d38d53..69408cd759 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/Authentication/OIDCAuthenticationPresenter.swift b/ElementX/Sources/Screens/Authentication/OIDCAuthenticationPresenter.swift index 9683ddb45f..03b20e502e 100644 --- a/ElementX/Sources/Screens/Authentication/OIDCAuthenticationPresenter.swift +++ b/ElementX/Sources/Screens/Authentication/OIDCAuthenticationPresenter.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import AuthenticationServices diff --git a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenCoordinator.swift b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenCoordinator.swift index 96092d5e9a..37bd5f4845 100644 --- a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenModels.swift b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenModels.swift index 7fa10d43a9..d456b9ebaa 100644 --- a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenModels.swift +++ b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -28,6 +19,8 @@ struct ServerConfirmationScreenViewState: BindableState { var homeserverAddress: String /// The flow being attempted on the selected homeserver. let authenticationFlow: AuthenticationFlow + /// Whether or not the homeserver supports registration. + var homeserverSupportsRegistration = false /// The presentation anchor used for OIDC authentication. var window: UIWindow? @@ -46,14 +39,26 @@ struct ServerConfirmationScreenViewState: BindableState { switch authenticationFlow { case .login: if homeserverAddress == "matrix.org" { - return L10n.screenServerConfirmationMessageLoginMatrixDotOrg + L10n.screenServerConfirmationMessageLoginMatrixDotOrg } else if homeserverAddress == "element.io" { - return L10n.screenServerConfirmationMessageLoginElementDotIo + L10n.screenServerConfirmationMessageLoginElementDotIo } else { - return "" + "" } case .register: - return L10n.screenServerConfirmationMessageRegister + if canContinue { + L10n.screenServerConfirmationMessageRegister + } else { + L10n.errorAccountCreationNotPossible + } + } + } + + /// Whether or not it is valid to continue the flow. + var canContinue: Bool { + switch authenticationFlow { + case .login: true + case .register: homeserverSupportsRegistration } } } diff --git a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenViewModel.swift b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenViewModel.swift index f6a67ffca6..717c8f76fc 100644 --- a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenViewModel.swift +++ b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -27,14 +18,18 @@ class ServerConfirmationScreenViewModel: ServerConfirmationScreenViewModelType, } init(authenticationService: AuthenticationServiceProtocol, authenticationFlow: AuthenticationFlow) { - super.init(initialViewState: ServerConfirmationScreenViewState(homeserverAddress: authenticationService.homeserver.value.address, - authenticationFlow: authenticationFlow)) + let homeserver = authenticationService.homeserver.value + + super.init(initialViewState: ServerConfirmationScreenViewState(homeserverAddress: homeserver.address, + authenticationFlow: authenticationFlow, + homeserverSupportsRegistration: homeserver.supportsRegistration)) authenticationService.homeserver .receive(on: DispatchQueue.main) .sink { [weak self] homeserver in guard let self else { return } state.homeserverAddress = homeserver.address + state.homeserverSupportsRegistration = homeserver.supportsRegistration } .store(in: &cancellables) } @@ -53,3 +48,9 @@ class ServerConfirmationScreenViewModel: ServerConfirmationScreenViewModelType, } } } + +extension LoginHomeserver { + var supportsRegistration: Bool { + loginMode == .oidc || (address == "matrix.org" && registrationHelperURL != nil) + } +} diff --git a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenViewModelProtocol.swift b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenViewModelProtocol.swift index 24a7b658d0..995b19c5df 100644 --- a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/View/ServerConfirmationScreen.swift b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/View/ServerConfirmationScreen.swift index 57cca4815e..78fbed4289 100644 --- a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/View/ServerConfirmationScreen.swift +++ b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/View/ServerConfirmationScreen.swift @@ -1,19 +1,11 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // +import Compound import SwiftUI struct ServerConfirmationScreen: View { @@ -61,6 +53,7 @@ struct ServerConfirmationScreen: View { } .buttonStyle(.compound(.primary)) .accessibilityIdentifier(A11yIdentifiers.serverConfirmationScreen.continue) + .disabled(!context.viewState.canContinue) Button { context.send(viewAction: .changeServer) } label: { Text(L10n.screenServerConfirmationChangeServer) @@ -75,9 +68,9 @@ struct ServerConfirmationScreen: View { // MARK: - Previews struct ServerConfirmationScreen_Previews: PreviewProvider, TestablePreview { - static let loginViewModel = ServerConfirmationScreenViewModel(authenticationService: MockAuthenticationServiceProxy(), + static let loginViewModel = ServerConfirmationScreenViewModel(authenticationService: MockAuthenticationService(), authenticationFlow: .login) - static let registerViewModel = ServerConfirmationScreenViewModel(authenticationService: MockAuthenticationServiceProxy(), + static let registerViewModel = ServerConfirmationScreenViewModel(authenticationService: MockAuthenticationService(), authenticationFlow: .register) static var previews: some View { diff --git a/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/MockServerSelectionScreenState.swift b/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/MockServerSelectionScreenState.swift index 15758f2fa4..0c9408861e 100644 --- a/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/MockServerSelectionScreenState.swift +++ b/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/MockServerSelectionScreenState.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -29,7 +20,6 @@ enum MockServerSelectionScreenState: CaseIterable { return ServerSelectionScreenViewModel(homeserverAddress: "https://matrix.org", slidingSyncLearnMoreURL: ServiceLocator.shared.settings.slidingSyncLearnMoreURL, isModallyPresented: true) - case .emptyAddress: return ServerSelectionScreenViewModel(homeserverAddress: "", slidingSyncLearnMoreURL: ServiceLocator.shared.settings.slidingSyncLearnMoreURL, diff --git a/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/ServerSelectionScreenCoordinator.swift b/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/ServerSelectionScreenCoordinator.swift index e4e817b2c5..6459f24a9e 100644 --- a/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/ServerSelectionScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/ServerSelectionScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -30,6 +21,7 @@ enum ServerSelectionScreenCoordinatorAction { case dismiss } +// Note: This code was brought over from Riot, we should move the authentication service logic into the view model. final class ServerSelectionScreenCoordinator: CoordinatorProtocol { private let parameters: ServerSelectionScreenCoordinatorParameters private let userIndicatorController: UserIndicatorControllerProtocol diff --git a/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/ServerSelectionScreenModels.swift b/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/ServerSelectionScreenModels.swift index 03faa7014a..94eb3b09d8 100644 --- a/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/ServerSelectionScreenModels.swift +++ b/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/ServerSelectionScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/ServerSelectionScreenViewModel.swift b/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/ServerSelectionScreenViewModel.swift index 258f11a74e..57d12c3dbb 100644 --- a/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/ServerSelectionScreenViewModel.swift +++ b/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/ServerSelectionScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/ServerSelectionScreenViewModelProtocol.swift b/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/ServerSelectionScreenViewModelProtocol.swift index d7fbdc6de0..320c0842a6 100644 --- a/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/ServerSelectionScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/ServerSelectionScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/View/ServerSelectionScreen.swift b/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/View/ServerSelectionScreen.swift index 934cc06aad..b166aabc67 100644 --- a/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/View/ServerSelectionScreen.swift +++ b/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/View/ServerSelectionScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/MockSoftLogoutScreenState.swift b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/MockSoftLogoutScreenState.swift index 235d60b330..e5cf574f8a 100644 --- a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/MockSoftLogoutScreenState.swift +++ b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/MockSoftLogoutScreenState.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenCoordinator.swift b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenCoordinator.swift index 90ebf7a19e..db748aa4f6 100644 --- a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -41,6 +32,7 @@ enum SoftLogoutScreenCoordinatorResult: CustomStringConvertible { } } +// Note: This code was brought over from Riot, we should move the authentication service logic into the view model. final class SoftLogoutScreenCoordinator: CoordinatorProtocol { private let parameters: SoftLogoutScreenCoordinatorParameters private var viewModel: SoftLogoutScreenViewModelProtocol diff --git a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenModels.swift b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenModels.swift index 20b77998a5..e42b9f9f0c 100644 --- a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenModels.swift +++ b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenViewModel.swift b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenViewModel.swift index bfac1d2467..a3aa235033 100644 --- a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenViewModel.swift +++ b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenViewModelProtocol.swift b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenViewModelProtocol.swift index df224a8509..d5336f8dc7 100644 --- a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/View/SoftLogoutScreen.swift b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/View/SoftLogoutScreen.swift index d9a64f5dcb..a4192e689b 100644 --- a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/View/SoftLogoutScreen.swift +++ b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/View/SoftLogoutScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/Authentication/UIConstants.swift b/ElementX/Sources/Screens/Authentication/UIConstants.swift index db5e368d3c..2c743435fa 100644 --- a/ElementX/Sources/Screens/Authentication/UIConstants.swift +++ b/ElementX/Sources/Screens/Authentication/UIConstants.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/Authentication/WaitlistScreen/View/WaitingDialog.swift b/ElementX/Sources/Screens/Authentication/WaitlistScreen/View/WaitingDialog.swift deleted file mode 100644 index 289b72484a..0000000000 --- a/ElementX/Sources/Screens/Authentication/WaitlistScreen/View/WaitingDialog.swift +++ /dev/null @@ -1,93 +0,0 @@ -// -// Copyright 2023 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import SwiftUI - -/// A standardised layout for waiting dialogs shown during the onboarding flow. -struct WaitingDialog: View { - @Environment(\.horizontalSizeClass) private var horizontalSizeClass - @Environment(\.verticalSizeClass) private var verticalSizeClass - - /// Not using the default to allow the gradient to fill edge to edge. - private let horizontalPadding = 16.0 - /// The top padding of the content, used to keep the text below the image. - private var contentTopPadding: CGFloat { - if verticalSizeClass == .compact { - // Reduced value for iPhones in landscape. - return UIConstants.startScreenBreakerScreenTopPadding - } else if horizontalSizeClass == .compact { - // The default value for portrait iPhones. - return 2 * UIConstants.startScreenBreakerScreenTopPadding - } else { - // Larger on iPad specifically for 11" in Landscape. - return 2.7 * UIConstants.startScreenBreakerScreenTopPadding - } - } - - /// The main content shown at the top of the layout. - @ViewBuilder var content: () -> Content - /// The content shown at the bottom of the layout. - @ViewBuilder var bottomContent: () -> BottomContent - - var body: some View { - FullscreenDialog(topPadding: UIConstants.startScreenBreakerScreenTopPadding, horizontalPadding: 0) { - content() - .padding(.top, contentTopPadding) - .padding(.horizontal, horizontalPadding) - } bottomContent: { - bottomContent() - .padding(.horizontal, horizontalPadding) - } - .background { - background - .ignoresSafeArea(edges: [.horizontal, .bottom]) - } - .ignoresSafeArea(edges: [.horizontal, .bottom]) - .environment(\.backgroundStyle, AnyShapeStyle(Color.compound.bgCanvasDefault)) - .environment(\.colorScheme, .dark) - .toolbar(.visible, for: .navigationBar) // Layout consistency in all states. - .toolbarBackground(.hidden, for: .navigationBar) - .preferredColorScheme(.light) // Has no effect on Previews, works fine in-app. - } - - var background: some View { - // Negative spacing to hide a rendering bug that shows the white background. - GeometryReader { geometry in - VStack(spacing: -5) { - Color.white - .frame(maxHeight: UIConstants.startScreenBreakerScreenTopPadding) - - Image(asset: Asset.Images.waitingGradient) - .resizable() - .frame(width: horizontalSizeClass == .compact ? nil : geometry.size.width) // Forced for landscape iPhone and nicer iPad. - .scaledToFit() - .layoutPriority(1) // Force for all landscape layouts. - - Color.compound.bgCanvasDefault - } - } - } -} - -struct WaitingDialog_Previews: PreviewProvider, TestablePreview { - static let viewModel = WaitlistScreenViewModel(homeserver: .mockMatrixDotOrg) - - static var previews: some View { - NavigationStack { - WaitlistScreen(context: viewModel.context) - } - } -} diff --git a/ElementX/Sources/Screens/Authentication/WaitlistScreen/View/WaitlistScreen.swift b/ElementX/Sources/Screens/Authentication/WaitlistScreen/View/WaitlistScreen.swift deleted file mode 100644 index 36b8ba2424..0000000000 --- a/ElementX/Sources/Screens/Authentication/WaitlistScreen/View/WaitlistScreen.swift +++ /dev/null @@ -1,92 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import SwiftUI - -struct WaitlistScreen: View { - @ObservedObject var context: WaitlistScreenViewModel.Context - - var body: some View { - WaitingDialog { - content - } bottomContent: { - buttons - } - .navigationBarBackButtonHidden() - .toolbar { toolbar } - } - - /// The main content of the view to be shown in a scroll view. - var content: some View { - VStack(spacing: 16) { - Text(context.viewState.title.tinting(".", color: Asset.Colors.brandColor.swiftUIColor)) - .font(.compound.headingXLBold) - .multilineTextAlignment(.center) - .foregroundColor(.compound.textPrimary) - .fixedSize(horizontal: false, vertical: true) - - Text(context.viewState.message) - .font(.compound.bodyLG) - .multilineTextAlignment(.center) - .foregroundColor(.compound.textPrimary) - } - } - - /// The action buttons shown at the bottom of the view. - @ViewBuilder - var buttons: some View { - if let userSession = context.viewState.userSession { - Button { context.send(viewAction: .continue(userSession)) } label: { - Text(L10n.actionContinue) - } - .buttonStyle(.compound(.primary)) - } - } - - @ToolbarContentBuilder - var toolbar: some ToolbarContent { - if context.viewState.isWaiting { - ToolbarItem(placement: .cancellationAction) { - Button(L10n.actionCancel) { - context.send(viewAction: .cancel) - } - } - } - } -} - -// MARK: - Previews - -struct WaitlistScreen_Previews: PreviewProvider, TestablePreview { - static let viewModel = WaitlistScreenViewModel(homeserver: .mockMatrixDotOrg) - static let successViewModel = { - let viewModel = WaitlistScreenViewModel(homeserver: .mockMatrixDotOrg) - viewModel.update(userSession: UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "@alice:matrix.org"))))) - return viewModel - }() - - static var previews: some View { - NavigationStack { - WaitlistScreen(context: viewModel.context) - } - .previewDisplayName("Waiting") - - NavigationStack { - WaitlistScreen(context: successViewModel.context) - } - .previewDisplayName("Success") - } -} diff --git a/ElementX/Sources/Screens/Authentication/WaitlistScreen/WaitlistScreenCoordinator.swift b/ElementX/Sources/Screens/Authentication/WaitlistScreen/WaitlistScreenCoordinator.swift deleted file mode 100644 index fa71258e21..0000000000 --- a/ElementX/Sources/Screens/Authentication/WaitlistScreen/WaitlistScreenCoordinator.swift +++ /dev/null @@ -1,128 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Combine -import SwiftUI - -struct WaitlistScreenCoordinatorParameters { - /// The credentials for the login. - let credentials: WaitlistScreenCredentials - /// The service used to authenticate the user. - let authenticationService: AuthenticationServiceProtocol - /// The service locator for the screen. - var userIndicatorController: UserIndicatorControllerProtocol = ServiceLocator.shared.userIndicatorController -} - -enum WaitlistScreenCoordinatorAction { - /// Login was successful after a retry attempt. - case signedIn(UserSessionProtocol) - /// The user would like to try sign in another way. - case cancel -} - -final class WaitlistScreenCoordinator: CoordinatorProtocol { - private let parameters: WaitlistScreenCoordinatorParameters - private var viewModel: WaitlistScreenViewModelProtocol - private let actionsSubject: PassthroughSubject = .init() - private var cancellables = Set() - private var refreshCancellable: AnyCancellable? - - var actions: AnyPublisher { - actionsSubject.eraseToAnyPublisher() - } - - init(parameters: WaitlistScreenCoordinatorParameters) { - self.parameters = parameters - - viewModel = WaitlistScreenViewModel(homeserver: parameters.credentials.homeserver) - - refreshCancellable = NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification) - .sink { [weak self] _ in - self?.refresh() - } - } - - func start() { - viewModel.actions.sink { [weak self] action in - guard let self else { return } - switch action { - case .cancel: - actionsSubject.send(.cancel) - case .continue(let userSession): - actionsSubject.send(.signedIn(userSession)) - } - } - .store(in: &cancellables) - } - - func toPresentable() -> AnyView { - AnyView(WaitlistScreen(context: viewModel.context)) - } - - // MARK: - Private - - /// Refresh the screen by retrying login to see if the waitlist has opened up. - private func refresh() { - guard parameters.credentials.homeserver == parameters.authenticationService.homeserver.value else { - MXLog.warning("Homeserver configuration changed.") - actionsSubject.send(.cancel) - return - } - - showRefreshIndicator() - - Task { - switch await parameters.authenticationService.login(username: parameters.credentials.username, - password: parameters.credentials.password, - initialDeviceName: parameters.credentials.initialDeviceName, - deviceID: parameters.credentials.deviceID) { - case .success(let userSession): - hideRefreshIndicator() - refreshCancellable = nil - viewModel.update(userSession: userSession) - case .failure(.isOnWaitlist): - hideRefreshIndicator() // Nothing to do, still waiting for availability. - case .failure(.invalidCredentials): - hideRefreshIndicator() - actionsSubject.send(.cancel) - case .failure: - hideRefreshIndicator() - showFailureIndicator() - } - } - } - - private static let refreshIndicatorID = "WaitlistCoordinatorRefresh" - private static let failureIndicatorID = "WaitlistCoordinatorFailure" - - private func showRefreshIndicator() { - parameters.userIndicatorController.submitIndicator(UserIndicator(id: Self.refreshIndicatorID, - type: .modal, - title: L10n.commonRefreshing, - persistent: true)) - } - - private func hideRefreshIndicator() { - parameters.userIndicatorController.retractIndicatorWithId(Self.refreshIndicatorID) - } - - private func showFailureIndicator() { - parameters.userIndicatorController.submitIndicator(UserIndicator(id: Self.failureIndicatorID, - type: .toast, - title: L10n.errorUnknown, - iconName: "xmark")) - } -} diff --git a/ElementX/Sources/Screens/Authentication/WaitlistScreen/WaitlistScreenModels.swift b/ElementX/Sources/Screens/Authentication/WaitlistScreen/WaitlistScreenModels.swift deleted file mode 100644 index 4599d9911d..0000000000 --- a/ElementX/Sources/Screens/Authentication/WaitlistScreen/WaitlistScreenModels.swift +++ /dev/null @@ -1,66 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation - -enum WaitlistScreenViewModelAction { - case cancel - case `continue`(UserSessionProtocol) -} - -/// The user's credentials used to retry login and refresh the waiting list. -struct WaitlistScreenCredentials: CustomStringConvertible, CustomDebugStringConvertible { - let username: String - let password: String - let initialDeviceName: String? - let deviceID: String? - - let homeserver: LoginHomeserver - - var description: String { "Redacted" } - var debugDescription: String { "Redacted" } -} - -struct WaitlistScreenViewState: BindableState { - /// The homeserver the user is waiting for. - let homeserver: LoginHomeserver - /// When refresh was successful, the user session that was returned by the login. - var userSession: UserSessionProtocol? - - /// Whether or not the user is still waiting in the queue. - var isWaiting: Bool { userSession == nil } - - var title: String { - if isWaiting { - return L10n.screenWaitlistTitle - } else { - return L10n.screenWaitlistTitleSuccess - } - } - - var message: String { - if isWaiting { - return L10n.screenWaitlistMessage(InfoPlistReader.main.bundleDisplayName, homeserver.address) - } else { - return L10n.screenWaitlistMessageSuccess(InfoPlistReader.main.bundleDisplayName) - } - } -} - -enum WaitlistScreenViewAction { - case cancel - case `continue`(UserSessionProtocol) -} diff --git a/ElementX/Sources/Screens/Authentication/WaitlistScreen/WaitlistScreenViewModel.swift b/ElementX/Sources/Screens/Authentication/WaitlistScreen/WaitlistScreenViewModel.swift deleted file mode 100644 index 02ba91c464..0000000000 --- a/ElementX/Sources/Screens/Authentication/WaitlistScreen/WaitlistScreenViewModel.swift +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Combine -import SwiftUI - -typealias WaitlistScreenViewModelType = StateStoreViewModel - -class WaitlistScreenViewModel: WaitlistScreenViewModelType, WaitlistScreenViewModelProtocol { - private var actionsSubject: PassthroughSubject = .init() - - var actions: AnyPublisher { - actionsSubject.eraseToAnyPublisher() - } - - init(homeserver: LoginHomeserver) { - super.init(initialViewState: WaitlistScreenViewState(homeserver: homeserver)) - } - - // MARK: - Public - - override func process(viewAction: WaitlistScreenViewAction) { - switch viewAction { - case .cancel: - actionsSubject.send(.cancel) - case .continue(let userSession): - actionsSubject.send(.continue(userSession)) - } - } - - func update(userSession: UserSessionProtocol) { - state.userSession = userSession - } -} diff --git a/ElementX/Sources/Screens/Authentication/WaitlistScreen/WaitlistScreenViewModelProtocol.swift b/ElementX/Sources/Screens/Authentication/WaitlistScreen/WaitlistScreenViewModelProtocol.swift deleted file mode 100644 index 9d62d1c487..0000000000 --- a/ElementX/Sources/Screens/Authentication/WaitlistScreen/WaitlistScreenViewModelProtocol.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Combine - -@MainActor -protocol WaitlistScreenViewModelProtocol { - var actions: AnyPublisher { get } - var context: WaitlistScreenViewModelType.Context { get } - - /// Set a user session on the screen to transition to the success state. - func update(userSession: UserSessionProtocol) -} diff --git a/ElementX/Sources/Screens/Authentication/WebRegistrationScreen/View/WebRegistrationScreen.swift b/ElementX/Sources/Screens/Authentication/WebRegistrationScreen/View/WebRegistrationScreen.swift new file mode 100644 index 0000000000..cdb1768b52 --- /dev/null +++ b/ElementX/Sources/Screens/Authentication/WebRegistrationScreen/View/WebRegistrationScreen.swift @@ -0,0 +1,139 @@ +// +// 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 +import WebKit + +struct WebRegistrationScreen: View { + @ObservedObject var context: WebRegistrationScreenViewModel.Context + + var body: some View { + NavigationStack { + WebRegistrationWebView(url: context.viewState.url, viewModelContext: context) + .navigationTitle(L10n.screenCreateAccountTitle) + .navigationBarTitleDisplayMode(.inline) + .toolbarBackground(.visible, for: .navigationBar) + .toolbar { + ToolbarItem(placement: .cancellationAction) { + Button(L10n.actionCancel) { + context.send(viewAction: .cancel) + } + } + } + } + } +} + +struct WebRegistrationWebView: UIViewRepresentable { + let url: URL + let viewModelContext: WebRegistrationScreenViewModel.Context + + func makeUIView(context: Context) -> WKWebView { + context.coordinator.webView + } + + func updateUIView(_ webView: WKWebView, context: Context) { } + + func makeCoordinator() -> Coordinator { + Coordinator(url: url, viewModelContext: viewModelContext) + } + + class Coordinator: NSObject, WKUIDelegate { + private let url: URL + private let viewModelContext: WebRegistrationScreenViewModel.Context + + private(set) var webView: WKWebView! + + init(url: URL, viewModelContext: WebRegistrationScreenViewModel.Context) { + self.url = url + self.viewModelContext = viewModelContext + + super.init() + + let eventHandlerName = "elementx" + let userContentController = WKUserContentController() + userContentController.add(WKScriptMessageHandlerWrapper(self), name: eventHandlerName) + + let eventHandlerScript = """ + window.addEventListener( + "mobileregistrationresponse", + (event) => { + window.webkit.messageHandlers.\(eventHandlerName).postMessage(JSON.stringify(event.detail)); + }, + false, + ); + """ + + let userScript = WKUserScript(source: eventHandlerScript, injectionTime: .atDocumentEnd, forMainFrameOnly: false) + userContentController.addUserScript(userScript) + + let configuration = WKWebViewConfiguration() + configuration.userContentController = userContentController + configuration.preferences.javaScriptCanOpenWindowsAutomatically = true + + webView = WKWebView(frame: .zero, configuration: configuration) + webView.uiDelegate = self + webView.load(URLRequest(url: url)) + } + + nonisolated func userContentController(_ userContentController: WKUserContentController, + didReceive message: WKScriptMessage) { + guard let jsonString = message.body as? String, let jsonData = jsonString.data(using: .utf8) else { + MXLog.error("Unexpected response.") + return + } + + guard let credentials = try? JSONDecoder().decode(WebRegistrationCredentials.self, from: jsonData) else { + MXLog.error("Invalid response.") + return + } + + MXLog.info("Received login credentials.") + Task { await viewModelContext.send(viewAction: .signedIn(credentials)) } + } + + // MARK: WKUIDelegate + + func webView(_ webView: WKWebView, + createWebViewWith configuration: WKWebViewConfiguration, + for navigationAction: WKNavigationAction, + windowFeatures: WKWindowFeatures) -> WKWebView? { + if let url = navigationAction.request.url, UIApplication.shared.canOpenURL(url) { + UIApplication.shared.open(url) + } + return nil + } + } + + /// Avoids retain loops between the configuration and webView coordinator + private class WKScriptMessageHandlerWrapper: NSObject, WKScriptMessageHandler { + private weak var coordinator: Coordinator? + + init(_ coordinator: Coordinator) { + self.coordinator = coordinator + } + + // MARK: WKScriptMessageHandler + + nonisolated func userContentController(_ userContentController: WKUserContentController, + didReceive message: WKScriptMessage) { + coordinator?.userContentController(userContentController, didReceive: message) + } + } +} + +// MARK: - Previews + +struct WebRegistrationScreen_Previews: PreviewProvider { + static let viewModel = WebRegistrationScreenViewModel(registrationHelperURL: "https://develop.element.io/#/mobile_register") + static var previews: some View { + NavigationStack { + WebRegistrationScreen(context: viewModel.context) + } + } +} diff --git a/ElementX/Sources/Screens/Authentication/WebRegistrationScreen/WebRegistrationScreenCoordinator.swift b/ElementX/Sources/Screens/Authentication/WebRegistrationScreen/WebRegistrationScreenCoordinator.swift new file mode 100644 index 0000000000..4443959575 --- /dev/null +++ b/ElementX/Sources/Screens/Authentication/WebRegistrationScreen/WebRegistrationScreenCoordinator.swift @@ -0,0 +1,83 @@ +// +// 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 MatrixRustSDK +import SwiftUI + +struct WebRegistrationScreenCoordinatorParameters { + /// The service used to authenticate the user. + let authenticationService: AuthenticationServiceProtocol + + let userIndicatorController: UserIndicatorControllerProtocol +} + +enum WebRegistrationScreenCoordinatorAction: CustomStringConvertible { + case cancel + case signedIn(UserSessionProtocol) + + var description: String { + switch self { + case .cancel: "cancel" + case .signedIn: "signedIn" + } + } +} + +// Note: This code was based on the LoginScreen, we should move the authentication service logic into the view model. +final class WebRegistrationScreenCoordinator: CoordinatorProtocol { + private let parameters: WebRegistrationScreenCoordinatorParameters + private let viewModel: WebRegistrationScreenViewModelProtocol + + private var cancellables = Set() + + private let actionsSubject: PassthroughSubject = .init() + var actionsPublisher: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + init(parameters: WebRegistrationScreenCoordinatorParameters) { + self.parameters = parameters + + guard let registrationHelperURL = parameters.authenticationService.homeserver.value.registrationHelperURL else { + MXLog.error("Attempted registration without a helper URL.") + fatalError("A helper URL is required.") + } + viewModel = WebRegistrationScreenViewModel(registrationHelperURL: registrationHelperURL) + } + + func start() { + viewModel.actionsPublisher.sink { [weak self] action in + MXLog.info("Coordinator: received view model action: \(action)") + + guard let self else { return } + switch action { + case .cancel: + actionsSubject.send(.cancel) + case .signedIn(let credentials): + Task { await self.completeRegistration(using: credentials) } + } + } + .store(in: &cancellables) + } + + func toPresentable() -> AnyView { + AnyView(WebRegistrationScreen(context: viewModel.context)) + } + + // MARK: - Private + + private func completeRegistration(using credentials: WebRegistrationCredentials) async { + switch await parameters.authenticationService.completeWebRegistration(using: credentials) { + case .success(let userSession): + actionsSubject.send(.signedIn(userSession)) + case .failure(let error): + MXLog.error("Failed registration: \(error)") + parameters.userIndicatorController.alertInfo = .init(id: UUID(), title: L10n.errorUnknown, message: String(describing: error)) + } + } +} diff --git a/ElementX/Sources/Screens/Authentication/WebRegistrationScreen/WebRegistrationScreenModels.swift b/ElementX/Sources/Screens/Authentication/WebRegistrationScreen/WebRegistrationScreenModels.swift new file mode 100644 index 0000000000..324ae0c87b --- /dev/null +++ b/ElementX/Sources/Screens/Authentication/WebRegistrationScreen/WebRegistrationScreenModels.swift @@ -0,0 +1,51 @@ +// +// 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 WebRegistrationScreenViewModelAction: CustomStringConvertible { + case cancel + case signedIn(WebRegistrationCredentials) + + var description: String { + switch self { + case .cancel: "cancel" + case .signedIn: "signedIn" + } + } +} + +struct WebRegistrationScreenViewState: BindableState { + var url: URL + var bindings = WebRegistrationScreenViewStateBindings() +} + +struct WebRegistrationScreenViewStateBindings { } + +enum WebRegistrationScreenViewAction: CustomStringConvertible { + case cancel + case signedIn(WebRegistrationCredentials) + + var description: String { + switch self { + case .cancel: "cancel" + case .signedIn: "signedIn" + } + } +} + +struct WebRegistrationCredentials: Decodable { + let userID: String + let accessToken: String + let deviceID: String + + enum CodingKeys: String, CodingKey { + case userID = "user_id" + case accessToken = "access_token" + case deviceID = "device_id" + } +} diff --git a/ElementX/Sources/Screens/Authentication/WebRegistrationScreen/WebRegistrationScreenViewModel.swift b/ElementX/Sources/Screens/Authentication/WebRegistrationScreen/WebRegistrationScreenViewModel.swift new file mode 100644 index 0000000000..7c8cacc332 --- /dev/null +++ b/ElementX/Sources/Screens/Authentication/WebRegistrationScreen/WebRegistrationScreenViewModel.swift @@ -0,0 +1,34 @@ +// +// 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 MatrixRustSDK +import SwiftUI + +typealias WebRegistrationScreenViewModelType = StateStoreViewModel + +class WebRegistrationScreenViewModel: WebRegistrationScreenViewModelType, WebRegistrationScreenViewModelProtocol { + private let actionsSubject: PassthroughSubject = .init() + var actionsPublisher: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + init(registrationHelperURL: URL) { + super.init(initialViewState: WebRegistrationScreenViewState(url: registrationHelperURL)) + } + + override func process(viewAction: WebRegistrationScreenViewAction) { + MXLog.info("View model: received view action: \(viewAction)") + + switch viewAction { + case .cancel: + actionsSubject.send(.cancel) + case .signedIn(let credentials): + actionsSubject.send(.signedIn(credentials)) + } + } +} diff --git a/ElementX/Sources/Screens/Authentication/WebRegistrationScreen/WebRegistrationScreenViewModelProtocol.swift b/ElementX/Sources/Screens/Authentication/WebRegistrationScreen/WebRegistrationScreenViewModelProtocol.swift new file mode 100644 index 0000000000..2a5a6112bd --- /dev/null +++ b/ElementX/Sources/Screens/Authentication/WebRegistrationScreen/WebRegistrationScreenViewModelProtocol.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 WebRegistrationScreenViewModelProtocol { + var actionsPublisher: AnyPublisher { get } + var context: WebRegistrationScreenViewModelType.Context { get } +} diff --git a/ElementX/Sources/Screens/AuthenticationStartScreen/AuthenticationStartScreenCoordinator.swift b/ElementX/Sources/Screens/AuthenticationStartScreen/AuthenticationStartScreenCoordinator.swift index 067e4bf62f..c07bb65fc1 100644 --- a/ElementX/Sources/Screens/AuthenticationStartScreen/AuthenticationStartScreenCoordinator.swift +++ b/ElementX/Sources/Screens/AuthenticationStartScreen/AuthenticationStartScreenCoordinator.swift @@ -1,22 +1,17 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine import SwiftUI +struct AuthenticationStartScreenParameters { + let webRegistrationEnabled: Bool +} + final class AuthenticationStartScreenCoordinator: CoordinatorProtocol { private var viewModel: AuthenticationStartScreenViewModelProtocol private let actionsSubject: PassthroughSubject = .init() @@ -26,8 +21,8 @@ final class AuthenticationStartScreenCoordinator: CoordinatorProtocol { actionsSubject.eraseToAnyPublisher() } - init() { - viewModel = AuthenticationStartScreenViewModel() + init(parameters: AuthenticationStartScreenParameters) { + viewModel = AuthenticationStartScreenViewModel(webRegistrationEnabled: parameters.webRegistrationEnabled) } // MARK: - Public @@ -42,6 +37,8 @@ final class AuthenticationStartScreenCoordinator: CoordinatorProtocol { actionsSubject.send(.loginManually) case .loginWithQR: actionsSubject.send(.loginWithQR) + case .register: + actionsSubject.send(.register) case .reportProblem: actionsSubject.send(.reportProblem) } diff --git a/ElementX/Sources/Screens/AuthenticationStartScreen/AuthenticationStartScreenModels.swift b/ElementX/Sources/Screens/AuthenticationStartScreen/AuthenticationStartScreenModels.swift index 17fa13a108..3ae56e8719 100644 --- a/ElementX/Sources/Screens/AuthenticationStartScreen/AuthenticationStartScreenModels.swift +++ b/ElementX/Sources/Screens/AuthenticationStartScreen/AuthenticationStartScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -21,21 +12,25 @@ import SwiftUI enum AuthenticationStartScreenCoordinatorAction { case loginManually case loginWithQR + case register case reportProblem } enum AuthenticationStartScreenViewModelAction { case loginManually case loginWithQR + case register case reportProblem } struct AuthenticationStartScreenViewState: BindableState { - var isQRCodeLoginEnabled = false + let isWebRegistrationEnabled: Bool + let isQRCodeLoginEnabled: Bool } enum AuthenticationStartScreenViewAction { case loginManually case loginWithQR + case register case reportProblem } diff --git a/ElementX/Sources/Screens/AuthenticationStartScreen/AuthenticationStartScreenViewModel.swift b/ElementX/Sources/Screens/AuthenticationStartScreen/AuthenticationStartScreenViewModel.swift index 96e90ec1d8..10f9b16103 100644 --- a/ElementX/Sources/Screens/AuthenticationStartScreen/AuthenticationStartScreenViewModel.swift +++ b/ElementX/Sources/Screens/AuthenticationStartScreen/AuthenticationStartScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -26,9 +17,9 @@ class AuthenticationStartScreenViewModel: AuthenticationStartScreenViewModelType actionsSubject.eraseToAnyPublisher() } - init() { - super.init(initialViewState: AuthenticationStartScreenViewState()) - state.isQRCodeLoginEnabled = !ProcessInfo.processInfo.isiOSAppOnMac && AppSettings.isDevelopmentBuild + init(webRegistrationEnabled: Bool) { + super.init(initialViewState: AuthenticationStartScreenViewState(isWebRegistrationEnabled: webRegistrationEnabled, + isQRCodeLoginEnabled: !ProcessInfo.processInfo.isiOSAppOnMac && AppSettings.isDevelopmentBuild)) } override func process(viewAction: AuthenticationStartScreenViewAction) { @@ -37,6 +28,8 @@ class AuthenticationStartScreenViewModel: AuthenticationStartScreenViewModelType actionsSubject.send(.loginManually) case .loginWithQR: actionsSubject.send(.loginWithQR) + case .register: + actionsSubject.send(.register) case .reportProblem: actionsSubject.send(.reportProblem) } diff --git a/ElementX/Sources/Screens/AuthenticationStartScreen/AuthenticationStartScreenViewModelProtocol.swift b/ElementX/Sources/Screens/AuthenticationStartScreen/AuthenticationStartScreenViewModelProtocol.swift index bbd0f77e34..d36a23c294 100644 --- a/ElementX/Sources/Screens/AuthenticationStartScreen/AuthenticationStartScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/AuthenticationStartScreen/AuthenticationStartScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/AuthenticationStartScreen/View/AuthenticationStartLogo.swift b/ElementX/Sources/Screens/AuthenticationStartScreen/View/AuthenticationStartLogo.swift index af77ff16aa..bfc80f9556 100644 --- a/ElementX/Sources/Screens/AuthenticationStartScreen/View/AuthenticationStartLogo.swift +++ b/ElementX/Sources/Screens/AuthenticationStartScreen/View/AuthenticationStartLogo.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/AuthenticationStartScreen/View/AuthenticationStartScreen.swift b/ElementX/Sources/Screens/AuthenticationStartScreen/View/AuthenticationStartScreen.swift index ce99e54418..7871b47f35 100644 --- a/ElementX/Sources/Screens/AuthenticationStartScreen/View/AuthenticationStartScreen.swift +++ b/ElementX/Sources/Screens/AuthenticationStartScreen/View/AuthenticationStartScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -108,6 +99,14 @@ struct AuthenticationStartScreen: View { } .buttonStyle(.compound(.primary)) .accessibilityIdentifier(A11yIdentifiers.authenticationStartScreen.signIn) + + if context.viewState.isWebRegistrationEnabled { + Button { context.send(viewAction: .register) } label: { + Text(L10n.screenCreateAccountTitle) + .padding(14) + } + .buttonStyle(.compound(.plain)) + } } .padding(.horizontal, verticalSizeClass == .compact ? 128 : 24) .readableFrame() @@ -117,7 +116,7 @@ struct AuthenticationStartScreen: View { // MARK: - Previews struct AuthenticationStartScreen_Previews: PreviewProvider, TestablePreview { - static let viewModel = AuthenticationStartScreenViewModel() + static let viewModel = AuthenticationStartScreenViewModel(webRegistrationEnabled: true) static var previews: some View { AuthenticationStartScreen(context: viewModel.context) diff --git a/ElementX/Sources/Screens/AuthenticationStartScreen/View/AuthenticationStartScreenBackgroundImage.swift b/ElementX/Sources/Screens/AuthenticationStartScreen/View/AuthenticationStartScreenBackgroundImage.swift index f09890a2b3..b459c7bca1 100644 --- a/ElementX/Sources/Screens/AuthenticationStartScreen/View/AuthenticationStartScreenBackgroundImage.swift +++ b/ElementX/Sources/Screens/AuthenticationStartScreen/View/AuthenticationStartScreenBackgroundImage.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenCoordinator.swift b/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenCoordinator.swift index a5abd9b16a..b1c8202dc6 100644 --- a/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenCoordinator.swift +++ b/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenModels.swift b/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenModels.swift index 38387c6842..e402ee062c 100644 --- a/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenModels.swift +++ b/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenViewModel.swift b/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenViewModel.swift index e1724d6d93..67c6a8aaf9 100644 --- a/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenViewModel.swift +++ b/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -35,7 +26,7 @@ class BlockedUsersScreenViewModel: BlockedUsersScreenViewModelType, BlockedUsers let ignoredUsers = clientProxy.ignoredUsersPublisher.value?.map { UserProfileProxy(userID: $0) } super.init(initialViewState: BlockedUsersScreenViewState(blockedUsers: ignoredUsers ?? []), - imageProvider: mediaProvider) + mediaProvider: mediaProvider) showLoadingIndicator() diff --git a/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenViewModelProtocol.swift b/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenViewModelProtocol.swift index 162aea9187..80ed383c62 100644 --- a/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/BlockedUsersScreen/View/BlockedUsersScreen.swift b/ElementX/Sources/Screens/BlockedUsersScreen/View/BlockedUsersScreen.swift index ce456d8b84..977ae74a15 100644 --- a/ElementX/Sources/Screens/BlockedUsersScreen/View/BlockedUsersScreen.swift +++ b/ElementX/Sources/Screens/BlockedUsersScreen/View/BlockedUsersScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -54,7 +45,7 @@ struct BlockedUsersScreen: View { name: user.displayName, contentID: user.userID, avatarSize: .user(on: .blockedUsers), - imageProvider: context.imageProvider) + mediaProvider: context.mediaProvider) .accessibilityHidden(true) } } diff --git a/ElementX/Sources/Screens/BugReportScreen/BugReportScreenCoordinator.swift b/ElementX/Sources/Screens/BugReportScreen/BugReportScreenCoordinator.swift index f69bfa5937..e8324acf9e 100644 --- a/ElementX/Sources/Screens/BugReportScreen/BugReportScreenCoordinator.swift +++ b/ElementX/Sources/Screens/BugReportScreen/BugReportScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/BugReportScreen/BugReportScreenModels.swift b/ElementX/Sources/Screens/BugReportScreen/BugReportScreenModels.swift index df14fddb5b..b97d3060d0 100644 --- a/ElementX/Sources/Screens/BugReportScreen/BugReportScreenModels.swift +++ b/ElementX/Sources/Screens/BugReportScreen/BugReportScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/BugReportScreen/BugReportScreenViewModel.swift b/ElementX/Sources/Screens/BugReportScreen/BugReportScreenViewModel.swift index 5f6671815b..07f73fc66a 100644 --- a/ElementX/Sources/Screens/BugReportScreen/BugReportScreenViewModel.swift +++ b/ElementX/Sources/Screens/BugReportScreen/BugReportScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/BugReportScreen/BugReportScreenViewModelProtocol.swift b/ElementX/Sources/Screens/BugReportScreen/BugReportScreenViewModelProtocol.swift index 300306b044..a1807cb6c1 100644 --- a/ElementX/Sources/Screens/BugReportScreen/BugReportScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/BugReportScreen/BugReportScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/BugReportScreen/View/BugReportScreen.swift b/ElementX/Sources/Screens/BugReportScreen/View/BugReportScreen.swift index ebaaf8460d..d972d1279f 100644 --- a/ElementX/Sources/Screens/BugReportScreen/View/BugReportScreen.swift +++ b/ElementX/Sources/Screens/BugReportScreen/View/BugReportScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/CallScreen/CallScreenCoordinator.swift b/ElementX/Sources/Screens/CallScreen/CallScreenCoordinator.swift index bfdc7299d8..bc9a65ce31 100644 --- a/ElementX/Sources/Screens/CallScreen/CallScreenCoordinator.swift +++ b/ElementX/Sources/Screens/CallScreen/CallScreenCoordinator.swift @@ -1,34 +1,32 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // +import AVKit import Combine import SwiftUI struct CallScreenCoordinatorParameters { let elementCallService: ElementCallServiceProtocol - let clientProxy: ClientProxyProtocol - let roomProxy: RoomProxyProtocol - let clientID: String - let elementCallBaseURL: URL - let elementCallBaseURLOverride: URL? - let colorScheme: ColorScheme + let configuration: ElementCallConfiguration + let allowPictureInPicture: Bool let appHooks: AppHooks } enum CallScreenCoordinatorAction { + /// The call is able to be minimised to picture in picture with the provided controller. + /// + /// **Note:** Manually starting the PiP will not trigger the action below as we don't want + /// to change the app's navigation when backgrounding the app with the call screen visible. + case pictureInPictureIsAvailable(AVPictureInPictureController) + /// The call is still ongoing but the user requested to navigate around the app. + case pictureInPictureStarted + /// The call is hidden and the user wishes to return to it. + case pictureInPictureStopped + /// The call is finished and the screen is done with. case dismiss } @@ -43,12 +41,8 @@ final class CallScreenCoordinator: CoordinatorProtocol { init(parameters: CallScreenCoordinatorParameters) { viewModel = CallScreenViewModel(elementCallService: parameters.elementCallService, - clientProxy: parameters.clientProxy, - roomProxy: parameters.roomProxy, - clientID: parameters.clientID, - elementCallBaseURL: parameters.elementCallBaseURL, - elementCallBaseURLOverride: parameters.elementCallBaseURLOverride, - colorScheme: parameters.colorScheme, + configuration: parameters.configuration, + allowPictureInPicture: parameters.allowPictureInPicture, appHooks: parameters.appHooks) } @@ -57,6 +51,12 @@ final class CallScreenCoordinator: CoordinatorProtocol { guard let self else { return } switch action { + case .pictureInPictureIsAvailable(let controller): + actionsSubject.send(.pictureInPictureIsAvailable(controller)) + case .pictureInPictureStarted: + actionsSubject.send(.pictureInPictureStarted) + case .pictureInPictureStopped: + actionsSubject.send(.pictureInPictureStopped) case .dismiss: actionsSubject.send(.dismiss) } diff --git a/ElementX/Sources/Screens/CallScreen/CallScreenModels.swift b/ElementX/Sources/Screens/CallScreen/CallScreenModels.swift index c9098b11cd..bc312e49a7 100644 --- a/ElementX/Sources/Screens/CallScreen/CallScreenModels.swift +++ b/ElementX/Sources/Screens/CallScreen/CallScreenModels.swift @@ -1,22 +1,17 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // +import AVKit import Foundation enum CallScreenViewModelAction { + case pictureInPictureIsAvailable(AVPictureInPictureController) + case pictureInPictureStarted + case pictureInPictureStopped case dismiss } @@ -33,10 +28,19 @@ struct CallScreenViewState: BindableState { struct Bindings { var javaScriptMessageHandler: ((Any) -> Void)? var javaScriptEvaluator: ((String) async throws -> Any)? + var requestPictureInPictureHandler: (() async -> Result)? var alertInfo: AlertInfo? } enum CallScreenViewAction { case urlChanged(URL?) + case pictureInPictureIsAvailable(AVPictureInPictureController) + case navigateBack + case pictureInPictureWillStop + case endCall +} + +enum CallScreenError: Error { + case pictureInPictureNotAvailable } diff --git a/ElementX/Sources/Screens/CallScreen/CallScreenViewModel.swift b/ElementX/Sources/Screens/CallScreen/CallScreenViewModel.swift index a33536e721..abbc817bb6 100644 --- a/ElementX/Sources/Screens/CallScreen/CallScreenViewModel.swift +++ b/ElementX/Sources/Screens/CallScreen/CallScreenViewModel.swift @@ -1,19 +1,11 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // +import AVKit import CallKit import Combine import SwiftUI @@ -22,7 +14,8 @@ typealias CallScreenViewModelType = StateStoreViewModel WKWebView { - context.coordinator.webView + func makeUIView(context: Context) -> WebViewWrapper { + context.coordinator.webViewWrapper } func makeCoordinator() -> Coordinator { Coordinator(viewModelContext: viewModelContext) } - func updateUIView(_ webView: WKWebView, context: Context) { + func updateUIView(_ callWebView: WebViewWrapper, context: Context) { if let url { - context.coordinator.url = url - let request = URLRequest(url: url) - webView.load(request) + context.coordinator.load(url) } } @MainActor - class Coordinator: NSObject, WKUIDelegate, WKNavigationDelegate { + class Coordinator: NSObject, WKUIDelegate, WKNavigationDelegate, AVPictureInPictureControllerDelegate { private weak var viewModelContext: CallScreenViewModel.Context? private let certificateValidator: CertificateValidatorHookProtocol - private(set) var webView: WKWebView! + private var webView: WKWebView! + private var pictureInPictureController: AVPictureInPictureController? + private let pictureInPictureViewController: AVPictureInPictureVideoCallViewController + + /// The view to be shown in the app. This will contain the web view when picture in picture isn't running. + let webViewWrapper = WebViewWrapper(frame: .zero) - var url: URL! + private var url: URL! init(viewModelContext: CallScreenViewModel.Context) { self.viewModelContext = viewModelContext certificateValidator = viewModelContext.viewState.certificateValidator + pictureInPictureViewController = AVPictureInPictureVideoCallViewController() + pictureInPictureViewController.preferredContentSize = CGSize(width: 1920, height: 1080) super.init() - DispatchQueue.main.async { - // Avoid `Publishing changes from within view update warnings` - viewModelContext.javaScriptEvaluator = self.evaluateJavaScript(_:) + DispatchQueue.main.async { // Avoid `Publishing changes from within view update` warnings + viewModelContext.javaScriptEvaluator = self.evaluateJavaScript + viewModelContext.requestPictureInPictureHandler = self.requestPictureInPicture } let configuration = WKWebViewConfiguration() @@ -101,6 +120,22 @@ private struct WebView: UIViewRepresentable { webView.isOpaque = false webView.backgroundColor = .compound.bgCanvasDefault webView.scrollView.backgroundColor = .compound.bgCanvasDefault + + webViewWrapper.addMatchedSubview(webView) + + if AVPictureInPictureController.isPictureInPictureSupported() { + let pictureInPictureController = AVPictureInPictureController(contentSource: .init(activeVideoCallSourceView: webViewWrapper, + contentViewController: pictureInPictureViewController)) + pictureInPictureController.delegate = self + self.pictureInPictureController = pictureInPictureController + viewModelContext.send(viewAction: .pictureInPictureIsAvailable(pictureInPictureController)) + } + } + + func load(_ url: URL) { + self.url = url + let request = URLRequest(url: url) + webView.load(request) } func evaluateJavaScript(_ script: String) async throws -> Any? { @@ -162,6 +197,69 @@ private struct WebView: UIViewRepresentable { viewModelContext?.send(viewAction: .urlChanged(webView.url)) } } + + // MARK: - Picture in Picture + + func requestPictureInPicture() async -> Result { + guard let pictureInPictureController, + pictureInPictureController.isPictureInPicturePossible, + case .success(true) = await webViewCanEnterPictureInPicture() else { + return .failure(.pictureInPictureNotAvailable) + } + + pictureInPictureController.startPictureInPicture() + return .success(()) + } + + func stopPictureInPicture() { + pictureInPictureController?.stopPictureInPicture() + } + + nonisolated func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { + Task { @MainActor in + // We move the view via the delegate so it works when you background the app without calling requestPictureInPicture + pictureInPictureViewController.view.addMatchedSubview(webView) + _ = try? await evaluateJavaScript("controls.enablePip()") + } + } + + nonisolated func pictureInPictureControllerDidStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { + Task { @MainActor in + // Double check that the controller is definitely showing a page that supports picture in picture. + // This is necessary as it doesn't get checked when backgrounding the app or tapping a notification. + guard case .success(true) = await webViewCanEnterPictureInPicture() else { + MXLog.error("Picture in picture started on a webpage that doesn't support it. Ending the call.") + viewModelContext?.send(viewAction: .endCall) + return + } + } + } + + nonisolated func pictureInPictureControllerWillStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { + Task { await viewModelContext?.send(viewAction: .pictureInPictureWillStop) } + } + + nonisolated func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { + Task { @MainActor in + webViewWrapper.addMatchedSubview(webView) + _ = try? await evaluateJavaScript("controls.disablePip()") + } + } + + /// Whether the web view can do picture in picture or not (e.g. it is showing an error or the page didn't load). + private func webViewCanEnterPictureInPicture() async -> Result { + do { + guard let canEnterPictureInPicture = try await evaluateJavaScript("controls.canEnterPip()") as? Bool else { + MXLog.error("canEnterPip returned an unexpected value, skipping picture in picture.") + return .failure(.pictureInPictureNotAvailable) + } + MXLog.info("canEnterPip returned \(canEnterPictureInPicture)") + return .success(canEnterPictureInPicture) + } catch { + MXLog.error("Error checking canEnterPip: \(error)") + return .failure(.pictureInPictureNotAvailable) + } + } } /// Avoids retain loops between the configuration and webView coordinator @@ -187,9 +285,10 @@ struct CallScreen_Previews: PreviewProvider { static let viewModel = { let clientProxy = ClientProxyMock() clientProxy.getElementWellKnownReturnValue = .success(nil) + clientProxy.deviceID = "call-device-id" - let roomProxy = RoomProxyMock() - roomProxy.sendCallNotificationIfNeeededReturnValue = .success(()) + let roomProxy = JoinedRoomProxyMock() + roomProxy.sendCallNotificationIfNeededReturnValue = .success(()) let widgetDriver = ElementCallWidgetDriverMock() widgetDriver.underlyingMessagePublisher = .init() @@ -199,12 +298,13 @@ struct CallScreen_Previews: PreviewProvider { roomProxy.elementCallWidgetDriverDeviceIDReturnValue = widgetDriver return CallScreenViewModel(elementCallService: ElementCallServiceMock(.init()), - clientProxy: clientProxy, - roomProxy: roomProxy, - clientID: "io.element.elementx", - elementCallBaseURL: "https://call.element.io", - elementCallBaseURLOverride: nil, - colorScheme: .light, + configuration: .init(roomProxy: roomProxy, + clientProxy: clientProxy, + clientID: "io.element.elementx", + elementCallBaseURL: "https://call.element.io", + elementCallBaseURLOverride: nil, + colorScheme: .light), + allowPictureInPicture: false, appHooks: AppHooks()) }() diff --git a/ElementX/Sources/Screens/CreatePollScreen/PollFormScreenCoordinator.swift b/ElementX/Sources/Screens/CreatePollScreen/PollFormScreenCoordinator.swift index 7fe0976072..da8ad6f120 100644 --- a/ElementX/Sources/Screens/CreatePollScreen/PollFormScreenCoordinator.swift +++ b/ElementX/Sources/Screens/CreatePollScreen/PollFormScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/CreatePollScreen/PollFormScreenModels.swift b/ElementX/Sources/Screens/CreatePollScreen/PollFormScreenModels.swift index 7901310959..efc58e9bf2 100644 --- a/ElementX/Sources/Screens/CreatePollScreen/PollFormScreenModels.swift +++ b/ElementX/Sources/Screens/CreatePollScreen/PollFormScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/CreatePollScreen/PollFormScreenViewModel.swift b/ElementX/Sources/Screens/CreatePollScreen/PollFormScreenViewModel.swift index 08bdca2449..1e750d7911 100644 --- a/ElementX/Sources/Screens/CreatePollScreen/PollFormScreenViewModel.swift +++ b/ElementX/Sources/Screens/CreatePollScreen/PollFormScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/CreatePollScreen/PollFormScreenViewModelProtocol.swift b/ElementX/Sources/Screens/CreatePollScreen/PollFormScreenViewModelProtocol.swift index 2935156c7b..6dad3a123a 100644 --- a/ElementX/Sources/Screens/CreatePollScreen/PollFormScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/CreatePollScreen/PollFormScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/CreatePollScreen/View/PollFormScreen.swift b/ElementX/Sources/Screens/CreatePollScreen/View/PollFormScreen.swift index 7fbf887480..16f85e5299 100644 --- a/ElementX/Sources/Screens/CreatePollScreen/View/PollFormScreen.swift +++ b/ElementX/Sources/Screens/CreatePollScreen/View/PollFormScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/CreateRoom/CreateRoomCoordinator.swift b/ElementX/Sources/Screens/CreateRoom/CreateRoomCoordinator.swift index cb31473494..da965f2e2f 100644 --- a/ElementX/Sources/Screens/CreateRoom/CreateRoomCoordinator.swift +++ b/ElementX/Sources/Screens/CreateRoom/CreateRoomCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/CreateRoom/CreateRoomModels.swift b/ElementX/Sources/Screens/CreateRoom/CreateRoomModels.swift index 9801e13eaf..87ef365a15 100644 --- a/ElementX/Sources/Screens/CreateRoom/CreateRoomModels.swift +++ b/ElementX/Sources/Screens/CreateRoom/CreateRoomModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift b/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift index 4e6e35d58a..e8d4e2da90 100644 --- a/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift +++ b/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -45,7 +36,7 @@ class CreateRoomViewModel: CreateRoomViewModelType, CreateRoomViewModelProtocol let bindings = CreateRoomViewStateBindings(roomName: parameters.name, roomTopic: parameters.topic, isRoomPrivate: parameters.isRoomPrivate) - super.init(initialViewState: CreateRoomViewState(selectedUsers: selectedUsers.value, bindings: bindings), imageProvider: userSession.mediaProvider) + super.init(initialViewState: CreateRoomViewState(selectedUsers: selectedUsers.value, bindings: bindings), mediaProvider: userSession.mediaProvider) createRoomParameters .map(\.avatarImageMedia) diff --git a/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModelProtocol.swift b/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModelProtocol.swift index d3aa120a47..93b8a49200 100644 --- a/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModelProtocol.swift +++ b/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift b/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift index 982d75f4b2..32eb00b9e1 100644 --- a/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift +++ b/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -130,7 +121,7 @@ struct CreateRoomScreen: View { ScrollView(.horizontal, showsIndicators: false) { LazyHStack(spacing: 16) { ForEach(context.viewState.selectedUsers, id: \.userID) { user in - InviteUsersScreenSelectedItem(user: user, imageProvider: context.imageProvider) { + InviteUsersScreenSelectedItem(user: user, mediaProvider: context.mediaProvider) { context.send(viewAction: .deselectUser(user)) } .frame(width: invitedUserCellWidth) diff --git a/ElementX/Sources/Screens/DeactivateAccountScreen/DeactivateAccountScreenCoordinator.swift b/ElementX/Sources/Screens/DeactivateAccountScreen/DeactivateAccountScreenCoordinator.swift new file mode 100644 index 0000000000..138700a30b --- /dev/null +++ b/ElementX/Sources/Screens/DeactivateAccountScreen/DeactivateAccountScreenCoordinator.swift @@ -0,0 +1,54 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Combine +import SwiftUI + +struct DeactivateAccountScreenCoordinatorParameters { + let clientProxy: ClientProxyProtocol + let userIndicatorController: UserIndicatorControllerProtocol +} + +enum DeactivateAccountScreenCoordinatorAction { + case accountDeactivated +} + +final class DeactivateAccountScreenCoordinator: CoordinatorProtocol { + private let parameters: DeactivateAccountScreenCoordinatorParameters + private let viewModel: DeactivateAccountScreenViewModelProtocol + + private var cancellables = Set() + + private let actionsSubject: PassthroughSubject = .init() + var actionsPublisher: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + init(parameters: DeactivateAccountScreenCoordinatorParameters) { + self.parameters = parameters + + viewModel = DeactivateAccountScreenViewModel(clientProxy: parameters.clientProxy, + userIndicatorController: parameters.userIndicatorController) + } + + func start() { + viewModel.actionsPublisher.sink { [weak self] action in + MXLog.info("Coordinator: received view model action: \(action)") + + guard let self else { return } + switch action { + case .accountDeactivated: + actionsSubject.send(.accountDeactivated) + } + } + .store(in: &cancellables) + } + + func toPresentable() -> AnyView { + AnyView(DeactivateAccountScreen(context: viewModel.context)) + } +} diff --git a/ElementX/Sources/Screens/DeactivateAccountScreen/DeactivateAccountScreenModels.swift b/ElementX/Sources/Screens/DeactivateAccountScreen/DeactivateAccountScreenModels.swift new file mode 100644 index 0000000000..992740fa9a --- /dev/null +++ b/ElementX/Sources/Screens/DeactivateAccountScreen/DeactivateAccountScreenModels.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 Foundation + +enum DeactivateAccountScreenViewModelAction { + case accountDeactivated +} + +struct DeactivateAccountScreenViewState: BindableState { + let info: AttributedString + let infoPoint1: AttributedString + let infoPoint2 = AttributedString(L10n.screenDeactivateAccountListItem2) + let infoPoint3 = AttributedString(L10n.screenDeactivateAccountListItem3) + let infoPoint4 = AttributedString(L10n.screenDeactivateAccountListItem4) + + var bindings = DeactivateAccountScreenViewStateBindings() + + init() { + let boldPlaceholder = "{bold}" + var attributedString = AttributedString(L10n.screenDeactivateAccountDescription(boldPlaceholder)) + var boldString = AttributedString(L10n.screenDeactivateAccountDescriptionBoldPart) + boldString.bold() + attributedString.replace(boldPlaceholder, with: boldString) + info = attributedString + + attributedString = AttributedString(L10n.screenDeactivateAccountListItem1(boldPlaceholder)) + boldString = AttributedString(L10n.screenDeactivateAccountListItem1BoldPart) + boldString.bold() + attributedString.replace(boldPlaceholder, with: boldString) + infoPoint1 = attributedString + } +} + +struct DeactivateAccountScreenViewStateBindings { + var password = "" + var eraseData = false + var alertInfo: AlertInfo? +} + +enum DeactivateAccountScreenAlert { + case confirmation + case deactivationFailed +} + +enum DeactivateAccountScreenViewAction { + case deactivate +} diff --git a/ElementX/Sources/Screens/DeactivateAccountScreen/DeactivateAccountScreenViewModel.swift b/ElementX/Sources/Screens/DeactivateAccountScreen/DeactivateAccountScreenViewModel.swift new file mode 100644 index 0000000000..09e5ee076e --- /dev/null +++ b/ElementX/Sources/Screens/DeactivateAccountScreen/DeactivateAccountScreenViewModel.swift @@ -0,0 +1,82 @@ +// +// 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 DeactivateAccountScreenViewModelType = StateStoreViewModel + +class DeactivateAccountScreenViewModel: DeactivateAccountScreenViewModelType, DeactivateAccountScreenViewModelProtocol { + private let clientProxy: ClientProxyProtocol + private let userIndicatorController: UserIndicatorControllerProtocol + + private let actionsSubject: PassthroughSubject = .init() + var actionsPublisher: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + init(clientProxy: ClientProxyProtocol, userIndicatorController: UserIndicatorControllerProtocol) { + self.clientProxy = clientProxy + self.userIndicatorController = userIndicatorController + + super.init(initialViewState: DeactivateAccountScreenViewState()) + } + + override func process(viewAction: DeactivateAccountScreenViewAction) { + MXLog.info("View model: received view action: \(viewAction)") + + switch viewAction { + case .deactivate: + showDeactivationConfirmation() + } + } + + // MARK: - Private + + private let deactivatingIndicatorID = "\(DeactivateAccountScreenViewModel.self)-Deactivating" + + func showDeactivationConfirmation() { + state.bindings.alertInfo = .init(id: .confirmation, + title: L10n.screenDeactivateAccountTitle, + message: L10n.screenDeactivateAccountConfirmationDialogContent, + primaryButton: .init(title: L10n.actionDeactivate, action: { + Task { await self.deactivateAccount() } + }), + secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) + } + + func deactivateAccount() async { + userIndicatorController.submitIndicator(UserIndicator(id: deactivatingIndicatorID, + type: .modal(progress: .indeterminate, interactiveDismissDisabled: true, allowsInteraction: false), + title: L10n.commonPleaseWait, + persistent: true)) + + MXLog.warning("Deactivating account.") + + switch await clientProxy.deactivateAccount(password: nil, eraseData: state.bindings.eraseData) { + case .success: + MXLog.info("Account deactivated (no password needed).") + actionsSubject.send(.accountDeactivated) + return + case .failure: + MXLog.info("Request failed, including password.") + } + + switch await clientProxy.deactivateAccount(password: state.bindings.password, eraseData: state.bindings.eraseData) { + case .success: + MXLog.info("Account deactivated.") + actionsSubject.send(.accountDeactivated) + return + case .failure(let failure): + MXLog.info("Deactivation failed \(failure).") + state.bindings.alertInfo = .init(id: .deactivationFailed, + title: L10n.errorUnknown, + message: String(describing: failure)) + userIndicatorController.retractIndicatorWithId(deactivatingIndicatorID) + } + } +} diff --git a/ElementX/Sources/Screens/DeactivateAccountScreen/DeactivateAccountScreenViewModelProtocol.swift b/ElementX/Sources/Screens/DeactivateAccountScreen/DeactivateAccountScreenViewModelProtocol.swift new file mode 100644 index 0000000000..4321e45bf3 --- /dev/null +++ b/ElementX/Sources/Screens/DeactivateAccountScreen/DeactivateAccountScreenViewModelProtocol.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 DeactivateAccountScreenViewModelProtocol { + var actionsPublisher: AnyPublisher { get } + var context: DeactivateAccountScreenViewModelType.Context { get } +} diff --git a/ElementX/Sources/Screens/DeactivateAccountScreen/View/DeactivateAccountScreen.swift b/ElementX/Sources/Screens/DeactivateAccountScreen/View/DeactivateAccountScreen.swift new file mode 100644 index 0000000000..cb894b25c2 --- /dev/null +++ b/ElementX/Sources/Screens/DeactivateAccountScreen/View/DeactivateAccountScreen.swift @@ -0,0 +1,102 @@ +// +// 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 DeactivateAccountScreen: View { + @ObservedObject var context: DeactivateAccountScreenViewModel.Context + + var body: some View { + Form { + infoSection + eraseDataSection + passwordSection + } + .compoundList() + .safeAreaInset(edge: .bottom) { + Button(L10n.actionDeactivateAccount, role: .destructive) { + context.send(viewAction: .deactivate) + } + .buttonStyle(.compound(.primary)) + .disabled(context.password.isEmpty) + .padding(16) + .background(Color.compound.bgSubtleSecondaryLevel0.ignoresSafeArea()) + } + .navigationTitle(L10n.screenDeactivateAccountTitle) + .navigationBarTitleDisplayMode(.inline) + .alert(item: $context.alertInfo) + } + + private var infoSection: some View { + ListRow(kind: .custom { + VStack(alignment: .leading, spacing: 16) { + Text(context.viewState.info) + + VStack(alignment: .leading, spacing: 8) { + InfoItem(title: context.viewState.infoPoint1) + InfoItem(title: context.viewState.infoPoint2) + InfoItem(title: context.viewState.infoPoint3) + InfoItem(title: context.viewState.infoPoint4, isSuccess: true) + } + } + .foregroundColor(.compound.textSecondary) + .font(.compound.bodyMD) + .listRowBackground(Color.clear) + }) + } + + private var eraseDataSection: some View { + Section { + ListRow(label: .plain(title: L10n.screenDeactivateAccountDeleteAllMessages), + kind: .toggle($context.eraseData)) + } footer: { + Text(L10n.screenDeactivateAccountDeleteAllMessagesNotice) + .compoundListSectionFooter() + } + } + + private var passwordSection: some View { + Section { + ListRow(label: .plain(title: L10n.commonPassword), + kind: .secureField(text: $context.password)) + .submitLabel(.done) + } header: { + Text(L10n.actionConfirmPassword) + .compoundListSectionHeader() + } + } +} + +private struct InfoItem: View { + let title: AttributedString + var isSuccess = false + + var body: some View { + Label { + Text(title).padding(.vertical, 1) + } icon: { + CompoundIcon(isSuccess ? \.check : \.close, + size: .small, + relativeTo: .compound.bodyMD) + .foregroundStyle(isSuccess ? .compound.iconSuccessPrimary : .compound.iconCriticalPrimary) + } + .labelStyle(.custom(spacing: 8, alignment: .top)) + } +} + +// MARK: - Previews + +struct DeactivateAccountScreen_Previews: PreviewProvider, TestablePreview { + static let viewModel = DeactivateAccountScreenViewModel(clientProxy: ClientProxyMock(.init()), + userIndicatorController: UserIndicatorControllerMock()) + static var previews: some View { + NavigationStack { + DeactivateAccountScreen(context: viewModel.context) + } + } +} diff --git a/ElementX/Sources/Screens/EmojiPickerScreen/EmojiPickerScreenCoordinator.swift b/ElementX/Sources/Screens/EmojiPickerScreen/EmojiPickerScreenCoordinator.swift index 9e5b55a588..b78648b6ec 100644 --- a/ElementX/Sources/Screens/EmojiPickerScreen/EmojiPickerScreenCoordinator.swift +++ b/ElementX/Sources/Screens/EmojiPickerScreen/EmojiPickerScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/EmojiPickerScreen/EmojiPickerScreenModels.swift b/ElementX/Sources/Screens/EmojiPickerScreen/EmojiPickerScreenModels.swift index c11d8a2cc0..5aa2c4cd95 100644 --- a/ElementX/Sources/Screens/EmojiPickerScreen/EmojiPickerScreenModels.swift +++ b/ElementX/Sources/Screens/EmojiPickerScreen/EmojiPickerScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/EmojiPickerScreen/EmojiPickerScreenViewModel.swift b/ElementX/Sources/Screens/EmojiPickerScreen/EmojiPickerScreenViewModel.swift index 3516ac60c3..ce71384ca6 100644 --- a/ElementX/Sources/Screens/EmojiPickerScreen/EmojiPickerScreenViewModel.swift +++ b/ElementX/Sources/Screens/EmojiPickerScreen/EmojiPickerScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/EmojiPickerScreen/EmojiPickerScreenViewModelProtocol.swift b/ElementX/Sources/Screens/EmojiPickerScreen/EmojiPickerScreenViewModelProtocol.swift index a3e07bdc3f..c21169cf01 100644 --- a/ElementX/Sources/Screens/EmojiPickerScreen/EmojiPickerScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/EmojiPickerScreen/EmojiPickerScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/EmojiPickerScreen/View/EmojiPickerScreen.swift b/ElementX/Sources/Screens/EmojiPickerScreen/View/EmojiPickerScreen.swift index d2e848ba1d..ddbbeb75be 100644 --- a/ElementX/Sources/Screens/EmojiPickerScreen/View/EmojiPickerScreen.swift +++ b/ElementX/Sources/Screens/EmojiPickerScreen/View/EmojiPickerScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -95,7 +86,7 @@ struct EmojiPickerScreen_Previews: PreviewProvider, TestablePreview { static var previews: some View { EmojiPickerScreen(context: viewModel.context, selectedEmojis: ["๐Ÿ˜€", "๐Ÿ˜„"]) .previewDisplayName("Screen") - .snapshot(delay: 0.5) + .snapshotPreferences(delay: 0.5) } } diff --git a/ElementX/Sources/Screens/EmojiPickerScreen/View/EmojiPickerScreenHeaderView.swift b/ElementX/Sources/Screens/EmojiPickerScreen/View/EmojiPickerScreenHeaderView.swift index 6225f42de0..a70a7fe56a 100644 --- a/ElementX/Sources/Screens/EmojiPickerScreen/View/EmojiPickerScreenHeaderView.swift +++ b/ElementX/Sources/Screens/EmojiPickerScreen/View/EmojiPickerScreenHeaderView.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetPasswordScreen/EncryptionResetPasswordScreenCoordinator.swift b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetPasswordScreen/EncryptionResetPasswordScreenCoordinator.swift index cfd5804e6c..3c2a969208 100644 --- a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetPasswordScreen/EncryptionResetPasswordScreenCoordinator.swift +++ b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetPasswordScreen/EncryptionResetPasswordScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetPasswordScreen/EncryptionResetPasswordScreenModels.swift b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetPasswordScreen/EncryptionResetPasswordScreenModels.swift index f40ac6b307..d228ab4037 100644 --- a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetPasswordScreen/EncryptionResetPasswordScreenModels.swift +++ b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetPasswordScreen/EncryptionResetPasswordScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetPasswordScreen/EncryptionResetPasswordScreenViewModel.swift b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetPasswordScreen/EncryptionResetPasswordScreenViewModel.swift index 46dd308991..ed73d1924f 100644 --- a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetPasswordScreen/EncryptionResetPasswordScreenViewModel.swift +++ b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetPasswordScreen/EncryptionResetPasswordScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetPasswordScreen/EncryptionResetPasswordScreenViewModelProtocol.swift b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetPasswordScreen/EncryptionResetPasswordScreenViewModelProtocol.swift index 1db9d7c7cf..90b065f378 100644 --- a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetPasswordScreen/EncryptionResetPasswordScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetPasswordScreen/EncryptionResetPasswordScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetPasswordScreen/View/EncryptionResetPasswordScreen.swift b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetPasswordScreen/View/EncryptionResetPasswordScreen.swift index 9a6216347c..20b934e1ce 100644 --- a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetPasswordScreen/View/EncryptionResetPasswordScreen.swift +++ b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetPasswordScreen/View/EncryptionResetPasswordScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -45,6 +36,7 @@ struct EncryptionResetPasswordScreen: View { } .buttonStyle(.compound(.primary)) } + .background() .backgroundStyle(.compound.bgCanvasDefault) .interactiveDismissDisabled() .onAppear { textFieldFocus = true } @@ -58,6 +50,7 @@ struct EncryptionResetPasswordScreen: View { .font(.compound.bodySMSemibold) SecureField(L10n.screenResetEncryptionPasswordPlaceholder, text: $context.password) + .tint(.compound.iconAccentTertiary) .frame(maxWidth: .infinity) .padding() .background(Color.compound.bgSubtleSecondaryLevel0) diff --git a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenCoordinator.swift b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenCoordinator.swift index f95ebbe7d0..b2f7edeeab 100644 --- a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenCoordinator.swift +++ b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenModels.swift b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenModels.swift index 335e7682b3..77ca459153 100644 --- a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenModels.swift +++ b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenViewModel.swift b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenViewModel.swift index 7582e0fe1b..ebdfda67bc 100644 --- a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenViewModel.swift +++ b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenViewModelProtocol.swift b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenViewModelProtocol.swift index 8eb9262b7a..2ebf141d12 100644 --- a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/View/EncryptionResetScreen.swift b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/View/EncryptionResetScreen.swift index 24924359d0..ab03039bcc 100644 --- a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/View/EncryptionResetScreen.swift +++ b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/View/EncryptionResetScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -24,7 +15,7 @@ struct EncryptionResetScreen: View { FullscreenDialog { mainContent } bottomContent: { - Button(L10n.actionContinue, role: .destructive) { + Button(L10n.screenEncryptionResetActionContinueReset, role: .destructive) { context.send(viewAction: .reset) } .buttonStyle(.compound(.primary)) @@ -48,18 +39,13 @@ struct EncryptionResetScreen: View { private var header: some View { VStack(spacing: 8) { - HeroImage(icon: \.error, style: .critical) + HeroImage(icon: \.error, style: .criticalOnSecondary) .padding(.bottom, 8) Text(L10n.screenEncryptionResetTitle) .font(.compound.headingMDBold) .multilineTextAlignment(.center) .foregroundColor(.compound.textPrimary) - - Text(L10n.screenEncryptionResetSubtitle) - .font(.compound.bodyMD) - .multilineTextAlignment(.center) - .foregroundColor(.compound.textSecondary) } } diff --git a/ElementX/Sources/Screens/FilePreviewScreen/InteractiveQuickLook.swift b/ElementX/Sources/Screens/FilePreviewScreen/InteractiveQuickLook.swift index 1573b557ef..42260d868d 100644 --- a/ElementX/Sources/Screens/FilePreviewScreen/InteractiveQuickLook.swift +++ b/ElementX/Sources/Screens/FilePreviewScreen/InteractiveQuickLook.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -21,14 +12,14 @@ import SwiftUI extension View { /// Preview a media file using a QuickLook Preview Controller. The preview is interactive with /// the dismiss gesture working as expected if it was presented from UIKit. - func interactiveQuickLook(item: Binding, shouldHideControls: Bool = false) -> some View { - modifier(InteractiveQuickLookModifier(item: item, shouldHideControls: shouldHideControls)) + func interactiveQuickLook(item: Binding, allowEditing: Bool = true) -> some View { + modifier(InteractiveQuickLookModifier(item: item, allowEditing: allowEditing)) } } private struct InteractiveQuickLookModifier: ViewModifier { @Binding var item: MediaPreviewItem? - let shouldHideControls: Bool + let allowEditing: Bool @State private var dismissalPublisher = PassthroughSubject() @@ -36,7 +27,7 @@ private struct InteractiveQuickLookModifier: ViewModifier { content.background { if let item { MediaPreviewViewController(previewItem: item, - shouldHideControls: shouldHideControls, + allowEditing: allowEditing, dismissalPublisher: dismissalPublisher) { self.item = nil } } else { // Work around QLPreviewController dismissal issues, see below. @@ -48,13 +39,13 @@ private struct InteractiveQuickLookModifier: ViewModifier { private struct MediaPreviewViewController: UIViewControllerRepresentable { let previewItem: MediaPreviewItem - let shouldHideControls: Bool + let allowEditing: Bool let dismissalPublisher: PassthroughSubject let onDismiss: () -> Void func makeUIViewController(context: Context) -> PreviewHostingController { PreviewHostingController(previewItem: previewItem, - shouldHideControls: shouldHideControls, + allowEditing: allowEditing, dismissalPublisher: dismissalPublisher, onDismiss: onDismiss) } @@ -67,19 +58,20 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable { /// animations and interactions which don't work if you represent it directly to SwiftUI ๐Ÿคทโ€โ™‚๏ธ class PreviewHostingController: UIViewController, QLPreviewControllerDataSource, QLPreviewControllerDelegate { let previewItem: MediaPreviewItem - let shouldHideControls: Bool + let allowEditing: Bool let onDismiss: () -> Void + let sourceView = UIView() private var dismissalObserver: AnyCancellable? var previewController: QLPreviewController? init(previewItem: MediaPreviewItem, - shouldHideControls: Bool, + allowEditing: Bool, dismissalPublisher: PassthroughSubject, onDismiss: @escaping () -> Void) { self.previewItem = previewItem - self.shouldHideControls = shouldHideControls + self.allowEditing = allowEditing self.onDismiss = onDismiss super.init(nibName: nil, bundle: nil) @@ -87,8 +79,11 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable { // The QLPreviewController will not automatically dismiss itself when the underlying view is removed // (e.g. switching rooms from a notification) and it continues to hold on to the whole hierarcy. // Manually tell it to dismiss itself here. - dismissalObserver = dismissalPublisher.sink { _ in - self.dismiss(animated: true) + dismissalObserver = dismissalPublisher.sink { [weak self] _ in + // Dispatching on main.async with weak self we avoid doing an extra dismiss if the view is presented on top of another modal + DispatchQueue.main.async { [weak self] in + self?.dismiss(animated: true) + } } } @@ -99,14 +94,27 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable { override func viewDidLoad() { view.backgroundColor = .clear + view.addSubview(sourceView) + + sourceView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + sourceView.centerXAnchor.constraint(equalTo: view.centerXAnchor), + sourceView.centerYAnchor.constraint(equalTo: view.bottomAnchor), + sourceView.widthAnchor.constraint(equalToConstant: 200), + sourceView.heightAnchor.constraint(equalToConstant: 200) + ]) } - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) + // Don't use viewWillAppear due to the following warning: + // Presenting view controller from detached view controller is not supported, + // and may result in incorrect safe area insets and a corrupt root presentation. Make sure is in + // the view controller hierarchy before presenting from it. Will become a hard exception in a future release. + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) guard self.previewController == nil else { return } - let previewController = (shouldHideControls ? NoControlsPreviewController() : QLPreviewController()) + let previewController = QLPreviewController() previewController.dataSource = self previewController.delegate = self present(previewController, animated: true) @@ -126,6 +134,14 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable { // MARK: QLPreviewControllerDelegate + func previewController(_ controller: QLPreviewController, editingModeFor previewItem: QLPreviewItem) -> QLPreviewItemEditingMode { + allowEditing ? .createCopy : .disabled + } + + func previewController(_ controller: QLPreviewController, transitionViewFor item: any QLPreviewItem) -> UIView? { + sourceView + } + func previewControllerDidDismiss(_ controller: QLPreviewController) { onDismiss() } @@ -145,28 +161,6 @@ class MediaPreviewItem: NSObject, QLPreviewItem { } } -private class NoControlsPreviewController: QLPreviewController { - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - - guard let navigationController = children.first as? UINavigationController else { - return - } - - // Remove top file details bar - navigationController.navigationBar.isHidden = true - - // Remove the toolbars and their buttons - navigationController.view.subviews.compactMap { $0 as? UIToolbar }.forEach { toolbar in - toolbar.subviews.forEach { item in - item.isHidden = true - } - - toolbar.isHidden = true - } - } -} - // MARK: - Previews struct PreviewView_Previews: PreviewProvider { @@ -176,7 +170,7 @@ struct PreviewView_Previews: PreviewProvider { static var previews: some View { MediaPreviewViewController(previewItem: previewItem, - shouldHideControls: false, + allowEditing: false, dismissalPublisher: .init()) { } } } diff --git a/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenCoordinator.swift b/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenCoordinator.swift index 97c59adef0..b9b3d02fc6 100644 --- a/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenCoordinator.swift +++ b/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -41,7 +32,7 @@ class GlobalSearchScreenCoordinator: CoordinatorProtocol { init(parameters: GlobalSearchScreenCoordinatorParameters) { viewModel = GlobalSearchScreenViewModel(roomSummaryProvider: parameters.roomSummaryProvider, - imageProvider: parameters.mediaProvider) + mediaProvider: parameters.mediaProvider) viewModel.actions .sink { [weak self] action in diff --git a/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenModels.swift b/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenModels.swift index 37e165d201..586a95647a 100644 --- a/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenModels.swift +++ b/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenViewModel.swift b/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenViewModel.swift index a64532fd87..ed85554fe0 100644 --- a/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenViewModel.swift +++ b/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -28,11 +19,11 @@ class GlobalSearchScreenViewModel: GlobalSearchScreenViewModelType, GlobalSearch } init(roomSummaryProvider: RoomSummaryProviderProtocol, - imageProvider: ImageProviderProtocol) { + mediaProvider: MediaProviderProtocol) { self.roomSummaryProvider = roomSummaryProvider super.init(initialViewState: GlobalSearchScreenViewState(bindings: .init(searchQuery: "")), - imageProvider: imageProvider) + mediaProvider: mediaProvider) roomSummaryProvider.roomListPublisher .receive(on: DispatchQueue.main) diff --git a/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenViewModelProtocol.swift b/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenViewModelProtocol.swift index c04785b823..0ec3ca4fee 100644 --- a/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/GlobalSearchScreen/View/GlobalSearchScreen.swift b/ElementX/Sources/Screens/GlobalSearchScreen/View/GlobalSearchScreen.swift index df81d231fb..25fbd5a2c8 100644 --- a/ElementX/Sources/Screens/GlobalSearchScreen/View/GlobalSearchScreen.swift +++ b/ElementX/Sources/Screens/GlobalSearchScreen/View/GlobalSearchScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -32,6 +23,7 @@ struct GlobalSearchScreen: View { GlobalSearchScreenListRow(room: room, context: context) .listRowBackground(backgroundColor(for: room)) .listRowInsets(.init()) + .contentShape(.rect) .onTapGesture { context.send(viewAction: .select(roomID: room.id)) } @@ -214,7 +206,7 @@ private class GlobalSearchTextField: UITextField { struct GlobalSearchScreen_Previews: PreviewProvider, TestablePreview { static let viewModel = GlobalSearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))), - imageProvider: MockMediaProvider()) + mediaProvider: MockMediaProvider()) static var previews: some View { NavigationStack { diff --git a/ElementX/Sources/Screens/GlobalSearchScreen/View/GlobalSearchScreenCell.swift b/ElementX/Sources/Screens/GlobalSearchScreen/View/GlobalSearchScreenCell.swift index f32aba0dcf..c298a5353a 100644 --- a/ElementX/Sources/Screens/GlobalSearchScreen/View/GlobalSearchScreenCell.swift +++ b/ElementX/Sources/Screens/GlobalSearchScreen/View/GlobalSearchScreenCell.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -37,7 +28,7 @@ struct GlobalSearchScreenListRow: View { if dynamicTypeSize < .accessibility3 { RoomAvatarImage(avatar: room.avatar, avatarSize: .room(on: .messageForwarding), - imageProvider: context.imageProvider) + mediaProvider: context.mediaProvider) .dynamicTypeSize(dynamicTypeSize < .accessibility1 ? dynamicTypeSize : .accessibility1) .accessibilityHidden(true) } @@ -46,7 +37,7 @@ struct GlobalSearchScreenListRow: View { struct GlobalSearchScreenListRow_Previews: PreviewProvider, TestablePreview { static let viewModel = GlobalSearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))), - imageProvider: MockMediaProvider()) + mediaProvider: MockMediaProvider()) static var previews: some View { List { diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenCoordinator.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenCoordinator.swift index f5e6795aa3..d9b7a2481f 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenCoordinator.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -33,6 +24,7 @@ enum HomeScreenCoordinatorAction { case presentStartChatScreen case presentGlobalSearch case presentRoomDirectorySearch + case logoutWithoutConfirmation case logout } @@ -73,14 +65,16 @@ final class HomeScreenCoordinator: CoordinatorProtocol { actionsSubject.send(.presentSettingsScreen) case .presentSecureBackupSettings: actionsSubject.send(.presentSecureBackupSettings) - case .logout: - actionsSubject.send(.logout) case .presentStartChatScreen: actionsSubject.send(.presentStartChatScreen) case .presentGlobalSearch: actionsSubject.send(.presentGlobalSearch) case .presentRoomDirectorySearch: actionsSubject.send(.presentRoomDirectorySearch) + case .logoutWithoutConfirmation: + actionsSubject.send(.logoutWithoutConfirmation) + case .logout: + actionsSubject.send(.logout) } } .store(in: &cancellables) diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift index b267d9cf94..96106f1ea9 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -28,6 +19,7 @@ enum HomeScreenViewModelAction { case presentStartChatScreen case presentGlobalSearch case presentRoomDirectorySearch + case logoutWithoutConfirmation case logout } @@ -40,7 +32,9 @@ enum HomeScreenViewAction { case startChat case confirmRecoveryKey case skipRecoveryKeyConfirmation - case updateVisibleItemRange(range: Range, isScrolling: Bool) + case confirmSlidingSyncUpgrade + case skipSlidingSyncUpgrade + case updateVisibleItemRange(Range) case globalSearch case markRoomAsUnread(roomIdentifier: String) case markRoomAsRead(roomIdentifier: String) @@ -52,15 +46,12 @@ enum HomeScreenViewAction { } enum HomeScreenRoomListMode: CustomStringConvertible { - case migration case skeletons case empty case rooms var description: String { switch self { - case .migration: - return "Showing account migration" case .skeletons: return "Showing placeholders" case .empty: @@ -71,10 +62,10 @@ enum HomeScreenRoomListMode: CustomStringConvertible { } } -enum SecurityBannerMode { +enum HomeScreenBannerMode { case none case dismissed - case recoveryKeyConfirmation + case show } struct HomeScreenViewState: BindableState { @@ -82,7 +73,9 @@ struct HomeScreenViewState: BindableState { var userDisplayName: String? var userAvatarURL: URL? - var securityBannerMode = SecurityBannerMode.none + var securityBannerMode = HomeScreenBannerMode.none + var slidingSyncMigrationBannerMode = HomeScreenBannerMode.none + var requiresExtraAccountSetup = false var rooms: [HomeScreenRoom] = [] @@ -120,11 +113,7 @@ struct HomeScreenViewState: BindableState { } var shouldShowFilters: Bool { - !bindings.isSearchFieldFocused - } - - var shouldShowRecoveryKeyConfirmationBanner: Bool { - securityBannerMode == .recoveryKeyConfirmation + !bindings.isSearchFieldFocused && roomListMode == .rooms } } diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift index ea3b631b7a..7b40e72d23 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift @@ -1,21 +1,13 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import AnalyticsEvents import Combine +import MatrixRustSDK import SwiftUI typealias HomeScreenViewModelType = StateStoreViewModel @@ -28,11 +20,6 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol private let roomSummaryProvider: RoomSummaryProviderProtocol? - private var migrationCancellable: AnyCancellable? - - private var visibleItemRangeObservationToken: AnyCancellable? - private let visibleItemRangePublisher = CurrentValueSubject<(range: Range, isScrolling: Bool), Never>((0..<0, false)) - private var actionsSubject: PassthroughSubject = .init() var actions: AnyPublisher { actionsSubject.eraseToAnyPublisher() @@ -51,7 +38,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol roomSummaryProvider = userSession.clientProxy.roomSummaryProvider super.init(initialViewState: .init(userID: userSession.clientProxy.userID), - imageProvider: userSession.mediaProvider) + mediaProvider: userSession.mediaProvider) userSession.clientProxy.userAvatarURLPublisher .receive(on: DispatchQueue.main) @@ -76,7 +63,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol state.requiresExtraAccountSetup = true if state.securityBannerMode != .dismissed { - state.securityBannerMode = .recoveryKeyConfirmation + state.securityBannerMode = .show } default: state.securityBannerMode = .none @@ -131,6 +118,10 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol setupRoomListSubscriptions() updateRooms() + + Task { + await checkSlidingSyncMigration() + } } // MARK: - Public @@ -142,24 +133,29 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol case .showRoomDetails(roomIdentifier: let roomIdentifier): actionsSubject.send(.presentRoomDetails(roomIdentifier: roomIdentifier)) case .leaveRoom(roomIdentifier: let roomIdentifier): - startLeaveRoomProcess(roomId: roomIdentifier) + startLeaveRoomProcess(roomID: roomIdentifier) case .confirmLeaveRoom(roomIdentifier: let roomIdentifier): - leaveRoom(roomId: roomIdentifier) + Task { await leaveRoom(roomID: roomIdentifier) } case .showSettings: actionsSubject.send(.presentSettingsScreen) case .confirmRecoveryKey: actionsSubject.send(.presentSecureBackupSettings) case .skipRecoveryKeyConfirmation: state.securityBannerMode = .dismissed - case .updateVisibleItemRange(let range, let isScrolling): - visibleItemRangePublisher.send((range, isScrolling)) + case .confirmSlidingSyncUpgrade: + appSettings.slidingSyncDiscovery = .native + actionsSubject.send(.logout) + case .skipSlidingSyncUpgrade: + state.slidingSyncMigrationBannerMode = .dismissed + case .updateVisibleItemRange(let range): + roomSummaryProvider?.updateVisibleRange(range) case .startChat: actionsSubject.send(.presentStartChatScreen) case .globalSearch: actionsSubject.send(.presentGlobalSearch) case .markRoomAsUnread(let roomIdentifier): Task { - guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomIdentifier) else { + guard case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomIdentifier) else { MXLog.error("Failed retrieving room for identifier: \(roomIdentifier)") return } @@ -173,7 +169,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol } case .markRoomAsRead(let roomIdentifier): Task { - guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomIdentifier) else { + guard case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomIdentifier) else { MXLog.error("Failed retrieving room for identifier: \(roomIdentifier)") return } @@ -206,12 +202,15 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol // perphery: ignore - used in release mode func presentCrashedLastRunAlert() { - state.bindings.alertInfo = AlertInfo(id: UUID(), - title: L10n.crashDetectionDialogContent(InfoPlistReader.main.bundleDisplayName), - primaryButton: .init(title: L10n.actionNo, action: nil), - secondaryButton: .init(title: L10n.actionYes) { [weak self] in - self?.actionsSubject.send(.presentFeedbackScreen) - }) + // Delay setting the alert otherwise it automatically gets dismissed. Same as the force logout one. + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + self.state.bindings.alertInfo = AlertInfo(id: UUID(), + title: L10n.crashDetectionDialogContent(InfoPlistReader.main.bundleDisplayName), + primaryButton: .init(title: L10n.actionNo, action: nil), + secondaryButton: .init(title: L10n.actionYes) { [weak self] in + self?.actionsSubject.send(.presentFeedbackScreen) + }) + } } // MARK: - Private @@ -235,27 +234,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol } analyticsService.signpost.beginFirstRooms() - - let hasUserBeenMigrated = appSettings.migratedAccounts[userSession.clientProxy.userID] == true - - if !hasUserBeenMigrated { - state.roomListMode = .migration - - MXLog.info("Account not migrated, setting view room list mode to \"\(state.roomListMode)\"") - - migrationCancellable = userSession.clientProxy.actionsPublisher - .receive(on: DispatchQueue.main) - .sink { [weak self] callback in - guard let self, case .receivedSyncUpdate = callback else { return } - migrationCancellable = nil - appSettings.migratedAccounts[userSession.clientProxy.userID] = true - - MXLog.info("Received first sync response, updating room list mode") - - updateRoomListMode(with: roomSummaryProvider.statePublisher.value) - } - } - + roomSummaryProvider.statePublisher .receive(on: DispatchQueue.main) .sink { [weak self] state in @@ -266,24 +245,14 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol .store(in: &cancellables) roomSummaryProvider.roomListPublisher - .dropFirst(1) // We don't care about its initial value .receive(on: DispatchQueue.main) .sink { [weak self] _ in self?.updateRooms() - - // Wait for the all rooms view to receive its first update before installing - // dynamic timeline modifiers - self?.installListRangeModifiers() } .store(in: &cancellables) } private func updateRoomListMode(with roomSummaryProviderState: RoomSummaryProviderState) { - guard appSettings.migratedAccounts[userSession.clientProxy.userID] == true else { - // Ignore room summary provider updates while "migrating" - return - } - let isLoadingData = !roomSummaryProviderState.isLoaded let hasNoRooms = roomSummaryProviderState.isLoaded && roomSummaryProviderState.totalNumberOfRooms == 0 @@ -315,27 +284,6 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol } } } - - private func installListRangeModifiers() { - guard visibleItemRangeObservationToken == nil else { - return - } - - visibleItemRangeObservationToken = visibleItemRangePublisher - .filter { $0.isScrolling == false } - .throttle(for: 0.5, scheduler: DispatchQueue.main, latest: true) - .removeDuplicates(by: { $0.isScrolling == $1.isScrolling && $0.range == $1.range }) - .sink { [weak self] value in - guard let self else { return } - - // Ignore scrolling while filtering rooms - guard self.state.bindings.searchQuery.isEmpty else { - return - } - - self.updateVisibleRange(value.range) - } - } private func updateRooms() { guard let roomSummaryProvider else { @@ -353,21 +301,39 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol state.rooms = rooms } - private func updateVisibleRange(_ range: Range) { - guard !range.isEmpty else { + /// Check whether we can inform the user about potential migrations + /// or have him logout as his proxy is no longer available + private func checkSlidingSyncMigration() async { + // Not logged in with a proxy, don't need to do anything + guard userSession.clientProxy.slidingSyncVersion.isProxy else { return } - guard let roomSummaryProvider else { - MXLog.error("Visible rooms summary provider unavailable") + let versions = await userSession.clientProxy.availableSlidingSyncVersions + + // Native not available, nothing we can do + guard versions.contains(.native) else { return } - roomSummaryProvider.updateVisibleRange(range) + if versions.contains(where: \.isProxy) { // Both available, prompt for migration + state.slidingSyncMigrationBannerMode = .show + } else { // The proxy has been removed and logout is needed + // Delay setting the alert otherwise it automatically gets dismissed. Same as the crashed last run one + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + self.state.bindings.alertInfo = AlertInfo(id: UUID(), + title: L10n.bannerMigrateToNativeSlidingSyncForceLogoutTitle, + primaryButton: .init(title: L10n.bannerMigrateToNativeSlidingSyncAction, + action: { [weak self] in + self?.appSettings.slidingSyncDiscovery = .native + self?.actionsSubject.send(.logoutWithoutConfirmation) + })) + } + } } private func markRoomAsFavourite(_ roomID: String, isFavourite: Bool) async { - guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) else { + guard case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomID) else { MXLog.error("Failed retrieving room for identifier: \(roomID)") return } @@ -382,53 +348,47 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol private static let leaveRoomLoadingID = "LeaveRoomLoading" - private func startLeaveRoomProcess(roomId: String) { + private func startLeaveRoomProcess(roomID: String) { Task { defer { userIndicatorController.retractIndicatorWithId(Self.leaveRoomLoadingID) } userIndicatorController.submitIndicator(UserIndicator(id: Self.leaveRoomLoadingID, type: .modal, title: L10n.commonLoading, persistent: true)) - let room = await userSession.clientProxy.roomForIdentifier(roomId) - - guard let room else { + guard case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomID) else { state.bindings.alertInfo = AlertInfo(id: UUID(), title: L10n.errorUnknown) return } - if room.isPublic { - state.bindings.leaveRoomAlertItem = LeaveRoomAlertItem(roomID: roomId, isDM: room.isEncryptedOneToOneRoom, state: .public) + if roomProxy.isPublic { + state.bindings.leaveRoomAlertItem = LeaveRoomAlertItem(roomID: roomID, isDM: roomProxy.isEncryptedOneToOneRoom, state: .public) } else { - state.bindings.leaveRoomAlertItem = if room.joinedMembersCount > 1 { - LeaveRoomAlertItem(roomID: roomId, isDM: room.isEncryptedOneToOneRoom, state: .private) + state.bindings.leaveRoomAlertItem = if roomProxy.joinedMembersCount > 1 { + LeaveRoomAlertItem(roomID: roomID, isDM: roomProxy.isEncryptedOneToOneRoom, state: .private) } else { - LeaveRoomAlertItem(roomID: roomId, isDM: room.isEncryptedOneToOneRoom, state: .empty) + LeaveRoomAlertItem(roomID: roomID, isDM: roomProxy.isEncryptedOneToOneRoom, state: .empty) } } } } - private func leaveRoom(roomId: String) { - Task { - defer { - userIndicatorController.retractIndicatorWithId(Self.leaveRoomLoadingID) - } - userIndicatorController.submitIndicator(UserIndicator(id: Self.leaveRoomLoadingID, type: .modal, title: L10n.commonLeavingRoom, persistent: true)) - - let room = await userSession.clientProxy.roomForIdentifier(roomId) - let result = await room?.leaveRoom() - - switch result { - case .none, .some(.failure): - state.bindings.alertInfo = AlertInfo(id: UUID(), title: L10n.errorUnknown) - case .some(.success): - userIndicatorController.submitIndicator(UserIndicator(id: UUID().uuidString, - type: .toast, - title: L10n.commonCurrentUserLeftRoom, - iconName: "checkmark")) - actionsSubject.send(.roomLeft(roomIdentifier: roomId)) - } + private func leaveRoom(roomID: String) async { + defer { + userIndicatorController.retractIndicatorWithId(Self.leaveRoomLoadingID) } + userIndicatorController.submitIndicator(UserIndicator(id: Self.leaveRoomLoadingID, type: .modal, title: L10n.commonLeavingRoom, persistent: true)) + + guard case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomID), + case .success = await roomProxy.leaveRoom() else { + state.bindings.alertInfo = AlertInfo(id: UUID(), title: L10n.errorUnknown) + return + } + + userIndicatorController.submitIndicator(UserIndicator(id: UUID().uuidString, + type: .toast, + title: L10n.commonCurrentUserLeftRoom, + iconName: "checkmark")) + actionsSubject.send(.roomLeft(roomIdentifier: roomID)) } // MARK: Invites @@ -440,7 +400,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol userIndicatorController.submitIndicator(UserIndicator(id: roomID, type: .modal, title: L10n.commonLoading, persistent: true)) - guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) else { + guard case let .invited(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomID) else { displayError() return } @@ -478,7 +438,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol userIndicatorController.submitIndicator(UserIndicator(id: roomID, type: .modal, title: L10n.commonLoading, persistent: true)) - guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) else { + guard case let .invited(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomID) else { displayError() return } @@ -496,3 +456,14 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol message: L10n.errorUnknown) } } + +extension SlidingSyncVersion { + var isProxy: Bool { + switch self { + case .proxy: + return true + default: + return false + } + } +} diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModelProtocol.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModelProtocol.swift index a2add2c9ed..f39c072bfb 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/HomeScreen/View/BloomView.swift b/ElementX/Sources/Screens/HomeScreen/View/BloomView.swift index 6b27dcc8cd..0ca6477af9 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/BloomView.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/BloomView.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -38,6 +29,6 @@ struct BloomView: View { name: context.viewState.userDisplayName, contentID: context.viewState.userID, avatarSize: .custom(256), - imageProvider: context.imageProvider) + mediaProvider: context.mediaProvider) } } diff --git a/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFilterModels.swift b/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFilterModels.swift index b6b8f479f3..ef245eec99 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFilterModels.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFilterModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFilterView.swift b/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFilterView.swift index ac200d3f7c..882705729a 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFilterView.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFilterView.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFiltersEmptyStateView.swift b/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFiltersEmptyStateView.swift index 2d74ff927e..9d28f73d69 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFiltersEmptyStateView.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFiltersEmptyStateView.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFiltersView.swift b/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFiltersView.swift index 83c6734f1e..c801fc8cb7 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFiltersView.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFiltersView.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift index f556269ff8..027e1819e7 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -148,7 +139,7 @@ struct HomeScreen: View { name: context.viewState.userDisplayName, contentID: context.viewState.userID, avatarSize: .user(on: .home), - imageProvider: context.imageProvider) + mediaProvider: context.mediaProvider) .accessibilityIdentifier(A11yIdentifiers.homeScreen.userAvatar) .overlayBadge(10, isBadged: context.viewState.requiresExtraAccountSetup) .compositingGroup() @@ -197,17 +188,11 @@ struct HomeScreen: View { // MARK: - Previews struct HomeScreen_Previews: PreviewProvider, TestablePreview { - static let migratingViewModel = viewModel(.migration) static let loadingViewModel = viewModel(.skeletons) static let emptyViewModel = viewModel(.empty) static let loadedViewModel = viewModel(.rooms) static var previews: some View { - NavigationStack { - HomeScreen(context: migratingViewModel.context) - } - .previewDisplayName("Migrating") - NavigationStack { HomeScreen(context: loadingViewModel.context) } @@ -217,24 +202,19 @@ struct HomeScreen_Previews: PreviewProvider, TestablePreview { HomeScreen(context: emptyViewModel.context) } .previewDisplayName("Empty") - .snapshot(delay: 4.0) + .snapshotPreferences(delay: 4.0) NavigationStack { HomeScreen(context: loadedViewModel.context) } .previewDisplayName("Loaded") - .snapshot(delay: 4.0) + .snapshotPreferences(delay: 4.0) } static func viewModel(_ mode: HomeScreenRoomListMode) -> HomeScreenViewModel { - let userID = mode == .migration ? "@unmigrated_alice:example.com" : "@alice:example.com" - - let appSettings = AppSettings() // This uses shared storage under the hood - appSettings.migratedAccounts[userID] = mode != .migration + let userID = "@alice:example.com" let roomSummaryProviderState: RoomSummaryProviderMockConfigurationState = switch mode { - case .migration: - .loading case .skeletons: .loading case .empty: @@ -250,7 +230,7 @@ struct HomeScreen_Previews: PreviewProvider, TestablePreview { return HomeScreenViewModel(userSession: userSession, analyticsService: ServiceLocator.shared.analytics, - appSettings: appSettings, + appSettings: ServiceLocator.shared.settings, selectedRoomPublisher: CurrentValueSubject(nil).asCurrentValuePublisher(), userIndicatorController: ServiceLocator.shared.userIndicatorController) } diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenContent.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenContent.swift index bd3305b4c9..ec65e9420a 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenContent.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenContent.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -25,13 +16,8 @@ struct HomeScreenContent: View { let scrollViewAdapter: ScrollViewAdapter var body: some View { - switch context.viewState.roomListMode { - case .migration: - migrationView - default: - roomList - .sentryTrace("\(Self.self)") - } + roomList + .sentryTrace("\(Self.self)") } private var roomList: some View { @@ -68,8 +54,6 @@ struct HomeScreenContent: View { .searchable(text: $context.searchQuery, placement: .navigationBarDrawer(displayMode: .always)) .compoundSearchField() .disableAutocorrection(true) - case .migration: - EmptyView() } } .introspect(.scrollView, on: .supportedVersions) { scrollView in @@ -136,13 +120,16 @@ struct HomeScreenContent: View { private var topSection: some View { // An empty VStack causes glitches within the room list if context.viewState.shouldShowFilters || - context.viewState.shouldShowRecoveryKeyConfirmationBanner { + context.viewState.securityBannerMode == .show || + context.viewState.slidingSyncMigrationBannerMode == .show { VStack(spacing: 0) { if context.viewState.shouldShowFilters { RoomListFiltersView(state: $context.filtersState) } - - if context.viewState.shouldShowRecoveryKeyConfirmationBanner { + + if context.viewState.slidingSyncMigrationBannerMode == .show { + HomeScreenSlidingSyncMigrationBanner(context: context) + } else if context.viewState.securityBannerMode == .show { HomeScreenRecoveryKeyConfirmationBanner(context: context) } } @@ -150,47 +137,6 @@ struct HomeScreenContent: View { } } - @ViewBuilder - private var migrationView: some View { - if UIDevice.current.isPhone { - if verticalSizeClass == .compact { - migrationViewContent - .frame(maxWidth: .infinity, maxHeight: .infinity) - } else { - WaitingDialog { - migrationViewContent - } bottomContent: { - EmptyView() - } - } - } else { - migrationViewContent - .frame(maxWidth: .infinity, maxHeight: .infinity) - } - } - - private var migrationViewContent: some View { - VStack(spacing: 16) { - ProgressView() - .tint(.compound.iconPrimary) - .padding(.bottom, 4) - - Text(L10n.screenMigrationTitle.tinting(".", color: Asset.Colors.brandColor.swiftUIColor)) - .minimumScaleFactor(0.01) - .font(.compound.headingXLBold) - .multilineTextAlignment(.center) - .foregroundColor(.compound.textPrimary) - - Text(L10n.screenMigrationMessage) - .minimumScaleFactor(0.01) - .font(.compound.bodyLG) - .multilineTextAlignment(.center) - .foregroundColor(.compound.textPrimary) - .accessibilityIdentifier(A11yIdentifiers.migrationScreen.message) - } - .padding(.horizontal) - } - /// Often times the scroll view's content size isn't correct yet when this method is called e.g. when cancelling a search /// Dispatch it with a delay to allow the UI to update and the computations to be correct /// Once we move to iOS 17 we should remove all of this and use scroll anchors instead @@ -200,6 +146,8 @@ struct HomeScreenContent: View { private func delayedUpdateVisibleRange() { guard let scrollView = scrollViewAdapter.scrollView, + scrollViewAdapter.isScrolling.value == false, // Ignore while scrolling + context.searchQuery.isEmpty == true, // Ignore while filtering context.viewState.visibleRooms.count > 0 else { return } @@ -215,6 +163,6 @@ struct HomeScreenContent: View { let lastIndex = Int(max(0.0, scrollView.contentOffset.y + scrollView.bounds.height) / cellHeight) // This will be deduped and throttled on the view model layer - context.send(viewAction: .updateVisibleItemRange(range: firstIndex.. HomeScreenViewModel { + let clientProxy = ClientProxyMock(.init()) + + let userSession = UserSessionMock(.init(clientProxy: clientProxy)) + + return HomeScreenViewModel(userSession: userSession, + analyticsService: ServiceLocator.shared.analytics, + appSettings: ServiceLocator.shared.settings, + selectedRoomPublisher: CurrentValueSubject(nil).asCurrentValuePublisher(), + userIndicatorController: ServiceLocator.shared.userIndicatorController) + } +} diff --git a/ElementX/Sources/Screens/HomeScreen/View/RoomDirectorySearchView.swift b/ElementX/Sources/Screens/HomeScreen/View/RoomDirectorySearchView.swift index 8c902250d8..46be66a1ca 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/RoomDirectorySearchView.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/RoomDirectorySearchView.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenCoordinator.swift b/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenCoordinator.swift index fd36828e8f..c0a6dccca5 100644 --- a/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenCoordinator.swift +++ b/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenModels.swift b/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenModels.swift index e52957bb68..46eb6ba234 100644 --- a/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenModels.swift +++ b/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -31,7 +22,7 @@ enum InviteUsersScreenViewModelAction { enum InviteUsersScreenRoomType { case draft - case room(roomProxy: RoomProxyProtocol) + case room(roomProxy: JoinedRoomProxyProtocol) } struct InviteUsersScreenViewState: BindableState { diff --git a/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenViewModel.swift b/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenViewModel.swift index 55f31122d8..53938e2497 100644 --- a/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenViewModel.swift +++ b/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -42,7 +33,7 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr self.userDiscoveryService = userDiscoveryService self.userIndicatorController = userIndicatorController - super.init(initialViewState: InviteUsersScreenViewState(selectedUsers: selectedUsers.value, isCreatingRoom: roomType.isCreatingRoom), imageProvider: mediaProvider) + super.init(initialViewState: InviteUsersScreenViewState(selectedUsers: selectedUsers.value, isCreatingRoom: roomType.isCreatingRoom), mediaProvider: mediaProvider) setupSubscriptions(selectedUsers: selectedUsers) fetchMembersIfNeeded() diff --git a/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenViewModelProtocol.swift b/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenViewModelProtocol.swift index cb576ff5ce..4d4f1126a4 100644 --- a/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreen.swift b/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreen.swift index dc661eaf22..067eb290c7 100644 --- a/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreen.swift +++ b/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -88,7 +79,7 @@ struct InviteUsersScreen: View { ForEach(context.viewState.usersSection.users, id: \.userID) { user in UserProfileListRow(user: user, membership: context.viewState.membershipState(user), - imageProvider: context.imageProvider, + mediaProvider: context.mediaProvider, kind: .multiSelection(isSelected: context.viewState.isUserSelected(user)) { context.send(viewAction: .toggleUser(user)) }) @@ -113,7 +104,7 @@ struct InviteUsersScreen: View { ScrollViewReader { scrollView in HStack(spacing: 16) { ForEach(context.viewState.selectedUsers, id: \.userID) { user in - InviteUsersScreenSelectedItem(user: user, imageProvider: context.imageProvider) { + InviteUsersScreenSelectedItem(user: user, mediaProvider: context.mediaProvider) { deselect(user) } .frame(width: cellWidth) diff --git a/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreenSelectedItem.swift b/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreenSelectedItem.swift index e08c09b28b..3f970c812a 100644 --- a/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreenSelectedItem.swift +++ b/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreenSelectedItem.swift @@ -1,24 +1,15 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI struct InviteUsersScreenSelectedItem: View { let user: UserProfileProxy - let imageProvider: ImageProviderProtocol? + let mediaProvider: MediaProviderProtocol? let dismissAction: () -> Void var body: some View { @@ -39,7 +30,7 @@ struct InviteUsersScreenSelectedItem: View { name: user.displayName, contentID: user.userID, avatarSize: .user(on: .inviteUsers), - imageProvider: imageProvider) + mediaProvider: mediaProvider) .overlay(alignment: .topTrailing) { Button(action: dismissAction) { Image(systemName: "xmark.circle.fill") @@ -59,7 +50,7 @@ struct InviteUsersScreenSelectedItem_Previews: PreviewProvider, TestablePreview ScrollView(.horizontal) { HStack(spacing: 28) { ForEach(people, id: \.userID) { user in - InviteUsersScreenSelectedItem(user: user, imageProvider: MockMediaProvider(), dismissAction: { }) + InviteUsersScreenSelectedItem(user: user, mediaProvider: MockMediaProvider(), dismissAction: { }) .frame(width: 72) } } diff --git a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenCoordinator.swift b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenCoordinator.swift index a7dfb7cf74..e669b42049 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenCoordinator.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenModels.swift b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenModels.swift index f5becd709c..f2c5d4ac60 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenModels.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift index efe4710774..da59f09bad 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -27,7 +18,7 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo private let userIndicatorController: UserIndicatorControllerProtocol private var roomPreviewDetails: RoomPreviewDetails? - private var roomProxy: RoomProxyProtocol? + private var room: RoomProxyType? private let actionsSubject: PassthroughSubject = .init() var actionsPublisher: AnyPublisher { @@ -46,7 +37,7 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo self.clientProxy = clientProxy self.userIndicatorController = userIndicatorController - super.init(initialViewState: JoinRoomScreenViewState(roomID: roomID), imageProvider: mediaProvider) + super.init(initialViewState: JoinRoomScreenViewState(roomID: roomID), mediaProvider: mediaProvider) Task { await loadRoomDetails() @@ -89,8 +80,8 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo // See if we known about the room locally and, if so, have that // take priority over the preview one. - if let roomProxy = await clientProxy.roomForIdentifier(roomID) { - self.roomProxy = roomProxy + if let room = await clientProxy.roomForIdentifier(roomID) { + self.room = room await updateRoomDetails() } @@ -106,8 +97,20 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo } private func updateRoomDetails() async { + var roomProxy: RoomProxyProtocol? + var inviter: RoomInviterDetails? + + switch room { + case .joined(let joinedRoomProxy): + roomProxy = joinedRoomProxy + case .invited(let invitedRoomProxy): + inviter = await invitedRoomProxy.inviter.flatMap(RoomInviterDetails.init) + roomProxy = invitedRoomProxy + default: + break + } + let name = roomProxy?.name ?? roomPreviewDetails?.name - let inviter = await roomProxy?.inviter.flatMap(RoomInviterDetails.init) state.roomDetails = JoinRoomScreenRoomDetails(name: name, topic: roomProxy?.topic ?? roomPreviewDetails?.topic, canonicalAlias: roomProxy?.canonicalAlias ?? roomPreviewDetails?.canonicalAlias, @@ -119,9 +122,18 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo } private func updateMode() { - if roomProxy?.membership == .invited || roomPreviewDetails?.isInvited ?? false { // Check invites first to show Accept/Decline buttons on public rooms. + // Check invites first to show Accept/Decline buttons on public rooms. + if case .invited = room { state.mode = .invited - } else if roomProxy?.isPublic ?? false || roomPreviewDetails?.isPublic ?? false { + return + } + + if roomPreviewDetails?.isInvited ?? false { + state.mode = .invited + return + } + + if roomPreviewDetails?.isPublic ?? false { state.mode = .join } else if roomPreviewDetails?.canKnock ?? false, allowKnocking { // Knocking is not supported yet, the flag is purely for preview tests. state.mode = .knock @@ -180,7 +192,7 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo userIndicatorController.submitIndicator(UserIndicator(id: roomID, type: .modal, title: L10n.commonLoading, persistent: true)) - guard let roomProxy = await clientProxy.roomForIdentifier(roomID) else { + guard case let .invited(roomProxy) = room else { userIndicatorController.submitIndicator(.init(title: L10n.errorUnknown)) return } diff --git a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModelProtocol.swift b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModelProtocol.swift index 11ccd7a258..19ca10f938 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift b/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift index dba25600da..6fa7093b6e 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -42,7 +33,7 @@ struct JoinRoomScreen: View { VStack(spacing: 16) { RoomAvatarImage(avatar: context.viewState.avatar, avatarSize: .room(on: .joinRoom), - imageProvider: context.imageProvider) + mediaProvider: context.mediaProvider) .dynamicTypeSize(dynamicTypeSize < .accessibility1 ? dynamicTypeSize : .accessibility1) VStack(spacing: 8) { @@ -63,7 +54,7 @@ struct JoinRoomScreen: View { } if let inviter = context.viewState.roomDetails?.inviter { - RoomInviterLabel(inviter: inviter, imageProvider: context.imageProvider) + RoomInviterLabel(inviter: inviter, mediaProvider: context.mediaProvider) .font(.compound.bodyMD) .foregroundStyle(.compound.textSecondary) } @@ -120,25 +111,25 @@ struct JoinRoomScreen_Previews: PreviewProvider, TestablePreview { JoinRoomScreen(context: unknownViewModel.context) } .previewDisplayName("Unknown") - .snapshot(delay: 0.25) + .snapshotPreferences(delay: 0.25) NavigationStack { JoinRoomScreen(context: knockViewModel.context) } .previewDisplayName("Knock") - .snapshot(delay: 0.25) + .snapshotPreferences(delay: 0.25) NavigationStack { JoinRoomScreen(context: joinViewModel.context) } .previewDisplayName("Join") - .snapshot(delay: 0.25) + .snapshotPreferences(delay: 0.25) NavigationStack { JoinRoomScreen(context: inviteViewModel.context) } .previewDisplayName("Invite") - .snapshot(delay: 0.25) + .snapshotPreferences(delay: 0.25) } static func makeViewModel(mode: JoinRoomScreenInteractionMode) -> JoinRoomScreenViewModel { diff --git a/ElementX/Sources/Screens/LocationSharing/LocationSharingScreenModels.swift b/ElementX/Sources/Screens/LocationSharing/LocationSharingScreenModels.swift index 680c1eccca..e0fbc2c966 100644 --- a/ElementX/Sources/Screens/LocationSharing/LocationSharingScreenModels.swift +++ b/ElementX/Sources/Screens/LocationSharing/LocationSharingScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import CoreLocation diff --git a/ElementX/Sources/Screens/LocationSharing/StaticLocationScreenCoordinator.swift b/ElementX/Sources/Screens/LocationSharing/StaticLocationScreenCoordinator.swift index f4d1be1c9a..f990ea27ca 100644 --- a/ElementX/Sources/Screens/LocationSharing/StaticLocationScreenCoordinator.swift +++ b/ElementX/Sources/Screens/LocationSharing/StaticLocationScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/LocationSharing/StaticLocationScreenViewModel.swift b/ElementX/Sources/Screens/LocationSharing/StaticLocationScreenViewModel.swift index 426f850a61..287c027561 100644 --- a/ElementX/Sources/Screens/LocationSharing/StaticLocationScreenViewModel.swift +++ b/ElementX/Sources/Screens/LocationSharing/StaticLocationScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/LocationSharing/StaticLocationScreenViewModelProtocol.swift b/ElementX/Sources/Screens/LocationSharing/StaticLocationScreenViewModelProtocol.swift index b2f324854f..cb1137a138 100644 --- a/ElementX/Sources/Screens/LocationSharing/StaticLocationScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/LocationSharing/StaticLocationScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/LocationSharing/View/StaticLocationScreen.swift b/ElementX/Sources/Screens/LocationSharing/View/StaticLocationScreen.swift index 98d24c0db4..7766beb66c 100644 --- a/ElementX/Sources/Screens/LocationSharing/View/StaticLocationScreen.swift +++ b/ElementX/Sources/Screens/LocationSharing/View/StaticLocationScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/LogViewerScreen/LogViewerScreenCoordinator.swift b/ElementX/Sources/Screens/LogViewerScreen/LogViewerScreenCoordinator.swift index 111756e535..e3cc8943a5 100644 --- a/ElementX/Sources/Screens/LogViewerScreen/LogViewerScreenCoordinator.swift +++ b/ElementX/Sources/Screens/LogViewerScreen/LogViewerScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/LogViewerScreen/LogViewerScreenModels.swift b/ElementX/Sources/Screens/LogViewerScreen/LogViewerScreenModels.swift index 814a8f7619..8d7cc8f54e 100644 --- a/ElementX/Sources/Screens/LogViewerScreen/LogViewerScreenModels.swift +++ b/ElementX/Sources/Screens/LogViewerScreen/LogViewerScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/LogViewerScreen/LogViewerScreenViewModel.swift b/ElementX/Sources/Screens/LogViewerScreen/LogViewerScreenViewModel.swift index d4333dc433..e0439b0313 100644 --- a/ElementX/Sources/Screens/LogViewerScreen/LogViewerScreenViewModel.swift +++ b/ElementX/Sources/Screens/LogViewerScreen/LogViewerScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/LogViewerScreen/LogViewerScreenViewModelProtocol.swift b/ElementX/Sources/Screens/LogViewerScreen/LogViewerScreenViewModelProtocol.swift index b808b2a561..872caa6bd2 100644 --- a/ElementX/Sources/Screens/LogViewerScreen/LogViewerScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/LogViewerScreen/LogViewerScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/LogViewerScreen/View/LogViewerScreen.swift b/ElementX/Sources/Screens/LogViewerScreen/View/LogViewerScreen.swift index ee0aac0032..cdb9cace9f 100644 --- a/ElementX/Sources/Screens/LogViewerScreen/View/LogViewerScreen.swift +++ b/ElementX/Sources/Screens/LogViewerScreen/View/LogViewerScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/MediaPickerScreen/CameraPicker.swift b/ElementX/Sources/Screens/MediaPickerScreen/CameraPicker.swift index e7d2546437..ae825d5df3 100644 --- a/ElementX/Sources/Screens/MediaPickerScreen/CameraPicker.swift +++ b/ElementX/Sources/Screens/MediaPickerScreen/CameraPicker.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/MediaPickerScreen/DocumentPicker.swift b/ElementX/Sources/Screens/MediaPickerScreen/DocumentPicker.swift index 62e5969bd6..8c53ba0c70 100644 --- a/ElementX/Sources/Screens/MediaPickerScreen/DocumentPicker.swift +++ b/ElementX/Sources/Screens/MediaPickerScreen/DocumentPicker.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/MediaPickerScreen/MediaPickerScreenCoordinator.swift b/ElementX/Sources/Screens/MediaPickerScreen/MediaPickerScreenCoordinator.swift index f286149376..5c7cd45fb3 100644 --- a/ElementX/Sources/Screens/MediaPickerScreen/MediaPickerScreenCoordinator.swift +++ b/ElementX/Sources/Screens/MediaPickerScreen/MediaPickerScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/MediaPickerScreen/PhotoLibraryPicker.swift b/ElementX/Sources/Screens/MediaPickerScreen/PhotoLibraryPicker.swift index 33b2165a31..c1b1a4ad34 100644 --- a/ElementX/Sources/Screens/MediaPickerScreen/PhotoLibraryPicker.swift +++ b/ElementX/Sources/Screens/MediaPickerScreen/PhotoLibraryPicker.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import PhotosUI diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenCoordinator.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenCoordinator.swift index 253ec3f215..42633e9b54 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenCoordinator.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -19,7 +10,7 @@ import SwiftUI struct MediaUploadPreviewScreenCoordinatorParameters { let userIndicatorController: UserIndicatorControllerProtocol - let roomProxy: RoomProxyProtocol + let roomProxy: JoinedRoomProxyProtocol let mediaUploadingPreprocessor: MediaUploadingPreprocessor let title: String? let url: URL diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift index e919f1f5d3..c471ab42a1 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift index a97369676c..bc46ef4dbe 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -22,7 +13,7 @@ typealias MediaUploadPreviewScreenViewModelType = StateStoreViewModel AnyView { - AnyView(WebView(url: parameters.url) - // This URL is stable, forces view reloads if this representable is ever reused for another url - .id(parameters.url) - .ignoresSafeArea(edges: .bottom) - .presentationDragIndicator(.visible)) - } -} - -private struct WebView: UIViewRepresentable { - let url: URL - - func makeUIView(context: Context) -> WKWebView { - context.coordinator.webView - } - - func makeCoordinator() -> Coordinator { - Coordinator(url: url) - } - - func updateUIView(_ webView: WKWebView, context: Context) { - webView.load(URLRequest(url: context.coordinator.url)) - } - - @MainActor - class Coordinator: NSObject, WKUIDelegate, WKNavigationDelegate { - let url: URL - private(set) var webView: WKWebView! - - init(url: URL) { - if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true) { - var fragmentQueryItems = urlComponents.fragmentQueryItems ?? [] - - fragmentQueryItems.removeAll { $0.name == GenericCallLinkQueryParameters.appPrompt } - fragmentQueryItems.removeAll { $0.name == GenericCallLinkQueryParameters.confineToRoom } - - fragmentQueryItems.append(.init(name: GenericCallLinkQueryParameters.appPrompt, value: "false")) - fragmentQueryItems.append(.init(name: GenericCallLinkQueryParameters.confineToRoom, value: "true")) - - urlComponents.fragmentQueryItems = fragmentQueryItems - - if let adjustedURL = urlComponents.url { - self.url = adjustedURL - } else { - MXLog.error("Failed adjusting URL with components: \(urlComponents)") - self.url = url - } - } else { - MXLog.error("Failed constructing URL components for url: \(url)") - self.url = url - } - - super.init() - - let configuration = WKWebViewConfiguration() - - configuration.allowsInlineMediaPlayback = true - configuration.allowsPictureInPictureMediaPlayback = true - - webView = WKWebView(frame: .zero, configuration: configuration) - webView.uiDelegate = self - } - - // MARK: - WKUIDelegate - - func webView(_ webView: WKWebView, decideMediaCapturePermissionsFor origin: WKSecurityOrigin, initiatedBy frame: WKFrameInfo, type: WKMediaCaptureType) async -> WKPermissionDecision { - // Don't allow permissions for domains different than what the call was started on - guard origin.host == url.host else { - return .deny - } - - return .grant - } - - // MARK: - WKNavigationDelegate - - func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction) async -> WKNavigationActionPolicy { - // Allow any content from the main URL. - if navigationAction.request.url?.host == url.host { - return .allow - } - - // Additionally allow any embedded content such as captchas. - if let targetFrame = navigationAction.targetFrame, !targetFrame.isMainFrame { - return .allow - } - - // Otherwise the request is invalid. - return .cancel - } - } -} diff --git a/ElementX/Sources/Screens/Other/PlaceholderScreenCoordinator.swift b/ElementX/Sources/Screens/Other/PlaceholderScreenCoordinator.swift index 14a5b324a6..10c7d7ac79 100644 --- a/ElementX/Sources/Screens/Other/PlaceholderScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Other/PlaceholderScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/Other/SplashScreenCoordinator.swift b/ElementX/Sources/Screens/Other/SplashScreenCoordinator.swift index b881d2c2ed..c817968262 100644 --- a/ElementX/Sources/Screens/Other/SplashScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Other/SplashScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/PinnedEventsTimelineScreen/PinnedEventsTimelineScreenCoordinator.swift b/ElementX/Sources/Screens/PinnedEventsTimelineScreen/PinnedEventsTimelineScreenCoordinator.swift index fd886d0e95..850f7026eb 100644 --- a/ElementX/Sources/Screens/PinnedEventsTimelineScreen/PinnedEventsTimelineScreenCoordinator.swift +++ b/ElementX/Sources/Screens/PinnedEventsTimelineScreen/PinnedEventsTimelineScreenCoordinator.swift @@ -1,33 +1,34 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine import SwiftUI -struct PinnedEventsTimelineScreenCoordinatorParameters { } +struct PinnedEventsTimelineScreenCoordinatorParameters { + let roomProxy: JoinedRoomProxyProtocol + let timelineController: RoomTimelineControllerProtocol + let mediaProvider: MediaProviderProtocol + let mediaPlayerProvider: MediaPlayerProviderProtocol + let voiceMessageMediaManager: VoiceMessageMediaManagerProtocol + let appMediator: AppMediatorProtocol +} enum PinnedEventsTimelineScreenCoordinatorAction { case dismiss - - // Consider adding CustomStringConvertible conformance if the actions contain PII + case displayUser(userID: String) + case presentLocationViewer(geoURI: GeoURI, description: String?) + case displayMessageForwarding(forwardingItem: MessageForwardingItem) + case displayRoomScreenWithFocussedPin(eventID: String) } final class PinnedEventsTimelineScreenCoordinator: CoordinatorProtocol { private let parameters: PinnedEventsTimelineScreenCoordinatorParameters private let viewModel: PinnedEventsTimelineScreenViewModelProtocol + private let timelineViewModel: TimelineViewModelProtocol private var cancellables = Set() @@ -39,7 +40,16 @@ final class PinnedEventsTimelineScreenCoordinator: CoordinatorProtocol { init(parameters: PinnedEventsTimelineScreenCoordinatorParameters) { self.parameters = parameters - viewModel = PinnedEventsTimelineScreenViewModel() + viewModel = PinnedEventsTimelineScreenViewModel(analyticsService: ServiceLocator.shared.analytics) + timelineViewModel = TimelineViewModel(roomProxy: parameters.roomProxy, + timelineController: parameters.timelineController, + mediaProvider: parameters.mediaProvider, + mediaPlayerProvider: parameters.mediaPlayerProvider, + voiceMessageMediaManager: parameters.voiceMessageMediaManager, + userIndicatorController: ServiceLocator.shared.userIndicatorController, + appMediator: parameters.appMediator, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) } func start() { @@ -53,9 +63,32 @@ final class PinnedEventsTimelineScreenCoordinator: CoordinatorProtocol { } } .store(in: &cancellables) + + timelineViewModel.actions.sink { [weak self] action in + MXLog.info("Coordinator: received timeline view model action: \(action)") + guard let self else { return } + + switch action { + case .tappedOnSenderDetails(let userID): + actionsSubject.send(.displayUser(userID: userID)) + case .displayMessageForwarding(let forwardingItem): + actionsSubject.send(.displayMessageForwarding(forwardingItem: forwardingItem)) + case .displayLocation(_, let geoURI, let description): + actionsSubject.send(.presentLocationViewer(geoURI: geoURI, description: description)) + case .viewInRoomTimeline(let eventID): + actionsSubject.send(.displayRoomScreenWithFocussedPin(eventID: eventID)) + // These other actions will not be handled in this view + case .displayEmojiPicker, .displayReportContent, .displayCameraPicker, .displayMediaPicker, + .displayDocumentPicker, .displayLocationPicker, .displayPollForm, .displayMediaUploadPreviewScreen, + .displayResolveSendFailure, .composer, .hasScrolled: + // These actions are not handled in this coordinator + break + } + } + .store(in: &cancellables) } func toPresentable() -> AnyView { - AnyView(PinnedEventsTimelineScreen(context: viewModel.context)) + AnyView(PinnedEventsTimelineScreen(context: viewModel.context, timelineContext: timelineViewModel.context)) } } diff --git a/ElementX/Sources/Screens/PinnedEventsTimelineScreen/PinnedEventsTimelineScreenModels.swift b/ElementX/Sources/Screens/PinnedEventsTimelineScreen/PinnedEventsTimelineScreenModels.swift index 40b07d635f..441a0bd736 100644 --- a/ElementX/Sources/Screens/PinnedEventsTimelineScreen/PinnedEventsTimelineScreenModels.swift +++ b/ElementX/Sources/Screens/PinnedEventsTimelineScreen/PinnedEventsTimelineScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -20,12 +11,7 @@ enum PinnedEventsTimelineScreenViewModelAction { case dismiss } -struct PinnedEventsTimelineScreenViewState: BindableState { - var title: String { - // TODO: Implement the non empty case - L10n.screenPinnedTimelineScreenTitleEmpty - } -} +struct PinnedEventsTimelineScreenViewState: BindableState { } enum PinnedEventsTimelineScreenViewAction { case close diff --git a/ElementX/Sources/Screens/PinnedEventsTimelineScreen/PinnedEventsTimelineScreenViewModel.swift b/ElementX/Sources/Screens/PinnedEventsTimelineScreen/PinnedEventsTimelineScreenViewModel.swift index 06580c7ab8..81cf8e5f9d 100644 --- a/ElementX/Sources/Screens/PinnedEventsTimelineScreen/PinnedEventsTimelineScreenViewModel.swift +++ b/ElementX/Sources/Screens/PinnedEventsTimelineScreen/PinnedEventsTimelineScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -20,12 +11,15 @@ import SwiftUI typealias PinnedEventsTimelineScreenViewModelType = StateStoreViewModel class PinnedEventsTimelineScreenViewModel: PinnedEventsTimelineScreenViewModelType, PinnedEventsTimelineScreenViewModelProtocol { + private let analyticsService: AnalyticsService + private let actionsSubject: PassthroughSubject = .init() var actionsPublisher: AnyPublisher { actionsSubject.eraseToAnyPublisher() } - init() { + init(analyticsService: AnalyticsService) { + self.analyticsService = analyticsService super.init(initialViewState: PinnedEventsTimelineScreenViewState()) } @@ -36,6 +30,7 @@ class PinnedEventsTimelineScreenViewModel: PinnedEventsTimelineScreenViewModelTy switch viewAction { case .close: + analyticsService.trackInteraction(name: .PinnedMessageBannerCloseListButton) actionsSubject.send(.dismiss) } } diff --git a/ElementX/Sources/Screens/PinnedEventsTimelineScreen/PinnedEventsTimelineScreenViewModelProtocol.swift b/ElementX/Sources/Screens/PinnedEventsTimelineScreen/PinnedEventsTimelineScreenViewModelProtocol.swift index 5743f7ea52..229b33ecdf 100644 --- a/ElementX/Sources/Screens/PinnedEventsTimelineScreen/PinnedEventsTimelineScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/PinnedEventsTimelineScreen/PinnedEventsTimelineScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/PinnedEventsTimelineScreen/View/PinnedEventsTimelineScreen.swift b/ElementX/Sources/Screens/PinnedEventsTimelineScreen/View/PinnedEventsTimelineScreen.swift index 912efee142..8e7f047115 100644 --- a/ElementX/Sources/Screens/PinnedEventsTimelineScreen/View/PinnedEventsTimelineScreen.swift +++ b/ElementX/Sources/Screens/PinnedEventsTimelineScreen/View/PinnedEventsTimelineScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -19,31 +10,65 @@ import SwiftUI struct PinnedEventsTimelineScreen: View { @ObservedObject var context: PinnedEventsTimelineScreenViewModel.Context + @ObservedObject var timelineContext: TimelineViewModel.Context + + private var title: String { + let pinnedEventIDs = timelineContext.viewState.pinnedEventIDs + guard !pinnedEventIDs.isEmpty else { + return L10n.screenPinnedTimelineScreenTitleEmpty + } + return L10n.screenPinnedTimelineScreenTitle(pinnedEventIDs.count) + } var body: some View { content - .navigationTitle(context.viewState.title) + .navigationTitle(title) .navigationBarTitleDisplayMode(.inline) .toolbar { toolbar } .background(.compound.bgCanvasDefault) + .interactiveDismissDisabled() + .interactiveQuickLook(item: $timelineContext.mediaPreviewItem) + .sheet(item: $timelineContext.debugInfo) { TimelineItemDebugView(info: $0) } + .sheet(item: $timelineContext.actionMenuInfo) { info in + let actions = TimelineItemMenuActionProvider(timelineItem: info.item, + canCurrentUserRedactSelf: timelineContext.viewState.canCurrentUserRedactSelf, + canCurrentUserRedactOthers: timelineContext.viewState.canCurrentUserRedactOthers, + canCurrentUserPin: timelineContext.viewState.canCurrentUserPin, + pinnedEventIDs: timelineContext.viewState.pinnedEventIDs, + isDM: timelineContext.viewState.isEncryptedOneToOneRoom, + isViewSourceEnabled: timelineContext.viewState.isViewSourceEnabled, + isPinnedEventsTimeline: timelineContext.viewState.isPinnedEventsTimeline) + .makeActions() + if let actions { + TimelineItemMenu(item: info.item, actions: actions) + .environmentObject(timelineContext) + } + } } + @ViewBuilder private var content: some View { - // TODO: Implement switching between empty state and timeline - VStack(spacing: 16) { - HeroImage(icon: \.pin, style: .normal) - Text(L10n.screenPinnedTimelineEmptyStateHeadline) - .font(.compound.headingSMSemibold) - .foregroundStyle(.compound.textPrimary) - .multilineTextAlignment(.center) - Text(L10n.screenPinnedTimelineEmptyStateDescription(L10n.actionPin)) - .font(.compound.bodyMD) - .foregroundStyle(.compound.textSecondary) - .multilineTextAlignment(.center) - Spacer() + if timelineContext.viewState.pinnedEventIDs.isEmpty { + VStack(spacing: 16) { + HeroImage(icon: \.pin, style: .normal) + Text(L10n.screenPinnedTimelineEmptyStateHeadline) + .font(.compound.headingSMSemibold) + .foregroundStyle(.compound.textPrimary) + .multilineTextAlignment(.center) + Text(L10n.screenPinnedTimelineEmptyStateDescription(L10n.actionPin)) + .font(.compound.bodyMD) + .foregroundStyle(.compound.textSecondary) + .multilineTextAlignment(.center) + Spacer() + } + .padding(.top, 48) + .padding(.horizontal, 16) + } else { + TimelineView() + .id(timelineContext.viewState.roomID) + .environmentObject(timelineContext) + .environment(\.focussedEventID, timelineContext.viewState.timelineViewState.focussedEvent?.eventID) } - .padding(.top, 48) - .padding(.horizontal, 16) } @ToolbarContentBuilder @@ -59,10 +84,25 @@ struct PinnedEventsTimelineScreen: View { // MARK: - Previews struct PinnedEventsTimelineScreen_Previews: PreviewProvider, TestablePreview { - static let viewModel = PinnedEventsTimelineScreenViewModel() + static let viewModel = PinnedEventsTimelineScreenViewModel(analyticsService: ServiceLocator.shared.analytics) + static let emptyTimelineViewModel: TimelineViewModel = { + let timelineController = MockRoomTimelineController(timelineKind: .pinned) + timelineController.timelineItems = [] + return TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")), + timelineController: timelineController, + mediaProvider: MockMediaProvider(), + mediaPlayerProvider: MediaPlayerProviderMock(), + voiceMessageMediaManager: VoiceMessageMediaManagerMock(), + userIndicatorController: UserIndicatorControllerMock(), + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) + }() + static var previews: some View { NavigationStack { - PinnedEventsTimelineScreen(context: viewModel.context) + PinnedEventsTimelineScreen(context: viewModel.context, timelineContext: emptyTimelineViewModel.context) } + .previewDisplayName("Empty") } } diff --git a/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenCoordinator.swift b/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenCoordinator.swift index 0abcedec94..0b512d7765 100644 --- a/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenCoordinator.swift +++ b/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenModels.swift b/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenModels.swift index 6472990243..4e20f9faa9 100644 --- a/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenModels.swift +++ b/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenViewModel.swift b/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenViewModel.swift index af4bf62f87..0589f87287 100644 --- a/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenViewModel.swift +++ b/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenViewModelProtocol.swift b/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenViewModelProtocol.swift index 9352c6739d..d472f31374 100644 --- a/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/QRCodeLoginScreen/View/QRCodeLoginScreen.swift b/ElementX/Sources/Screens/QRCodeLoginScreen/View/QRCodeLoginScreen.swift index 2727e0f585..a0a9a0b664 100644 --- a/ElementX/Sources/Screens/QRCodeLoginScreen/View/QRCodeLoginScreen.swift +++ b/ElementX/Sources/Screens/QRCodeLoginScreen/View/QRCodeLoginScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONnDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -275,7 +266,7 @@ struct QRCodeLoginScreen: View { case .connectionNotSecure: VStack(spacing: 40) { VStack(spacing: 16) { - HeroImage(icon: \.error, style: .critical) + HeroImage(icon: \.error, style: .criticalOnSecondary) VStack(spacing: 8) { Text(L10n.screenQrCodeLoginConnectionNoteSecureStateTitle) @@ -341,7 +332,7 @@ struct QRCodeLoginScreen: View { } VStack(spacing: 16) { - HeroImage(icon: \.error, style: .critical) + HeroImage(icon: \.error, style: .criticalOnSecondary) VStack(spacing: 8) { Text(title) diff --git a/ElementX/Sources/Screens/QRCodeLoginScreen/View/QRCodeScannerView.swift b/ElementX/Sources/Screens/QRCodeLoginScreen/View/QRCodeScannerView.swift index 613403c595..67e5fd8cdb 100644 --- a/ElementX/Sources/Screens/QRCodeLoginScreen/View/QRCodeScannerView.swift +++ b/ElementX/Sources/Screens/QRCodeLoginScreen/View/QRCodeScannerView.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import AVFoundation diff --git a/ElementX/Sources/Screens/ReportContentScreen/ReportContentScreenCoordinator.swift b/ElementX/Sources/Screens/ReportContentScreen/ReportContentScreenCoordinator.swift index f55d79fba3..5720f0fc4c 100644 --- a/ElementX/Sources/Screens/ReportContentScreen/ReportContentScreenCoordinator.swift +++ b/ElementX/Sources/Screens/ReportContentScreen/ReportContentScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -20,7 +11,7 @@ import SwiftUI struct ReportContentScreenCoordinatorParameters { let eventID: String let senderID: String - let roomProxy: RoomProxyProtocol + let roomProxy: JoinedRoomProxyProtocol let clientProxy: ClientProxyProtocol let userIndicatorController: UserIndicatorControllerProtocol } diff --git a/ElementX/Sources/Screens/ReportContentScreen/ReportContentScreenModels.swift b/ElementX/Sources/Screens/ReportContentScreen/ReportContentScreenModels.swift index 39676dadd4..1d4b9f9c25 100644 --- a/ElementX/Sources/Screens/ReportContentScreen/ReportContentScreenModels.swift +++ b/ElementX/Sources/Screens/ReportContentScreen/ReportContentScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/ReportContentScreen/ReportContentScreenViewModel.swift b/ElementX/Sources/Screens/ReportContentScreen/ReportContentScreenViewModel.swift index 4f90921ff4..0ef3c43e76 100644 --- a/ElementX/Sources/Screens/ReportContentScreen/ReportContentScreenViewModel.swift +++ b/ElementX/Sources/Screens/ReportContentScreen/ReportContentScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -22,7 +13,7 @@ typealias ReportContentScreenViewModelType = StateStoreViewModel = .init() @@ -30,7 +21,7 @@ class ReportContentScreenViewModel: ReportContentScreenViewModelType, ReportCont actionsSubject.eraseToAnyPublisher() } - init(eventID: String, senderID: String, roomProxy: RoomProxyProtocol, clientProxy: ClientProxyProtocol) { + init(eventID: String, senderID: String, roomProxy: JoinedRoomProxyProtocol, clientProxy: ClientProxyProtocol) { self.eventID = eventID self.senderID = senderID self.roomProxy = roomProxy diff --git a/ElementX/Sources/Screens/ReportContentScreen/ReportContentScreenViewModelProtocol.swift b/ElementX/Sources/Screens/ReportContentScreen/ReportContentScreenViewModelProtocol.swift index dd69da3ea7..9de037be81 100644 --- a/ElementX/Sources/Screens/ReportContentScreen/ReportContentScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/ReportContentScreen/ReportContentScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/ReportContentScreen/View/ReportContentScreen.swift b/ElementX/Sources/Screens/ReportContentScreen/View/ReportContentScreen.swift index 9d582b67a3..b8a6c85ccf 100644 --- a/ElementX/Sources/Screens/ReportContentScreen/View/ReportContentScreen.swift +++ b/ElementX/Sources/Screens/ReportContentScreen/View/ReportContentScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -77,7 +68,7 @@ struct ReportContentScreen: View { struct ReportContentScreen_Previews: PreviewProvider, TestablePreview { static let viewModel = ReportContentScreenViewModel(eventID: "", senderID: "", - roomProxy: RoomProxyMock(.init()), + roomProxy: JoinedRoomProxyMock(.init()), clientProxy: ClientProxyMock(.init())) static var previews: some View { diff --git a/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/ResolveVerifiedUserSendFailureScreenCoordinator.swift b/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/ResolveVerifiedUserSendFailureScreenCoordinator.swift new file mode 100644 index 0000000000..6331383322 --- /dev/null +++ b/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/ResolveVerifiedUserSendFailureScreenCoordinator.swift @@ -0,0 +1,67 @@ +// +// Copyright 2022 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Combine +import SwiftUI + +struct ResolveVerifiedUserSendFailureScreenCoordinatorParameters { + let failure: TimelineItemSendFailure.VerifiedUser + let itemID: TimelineItemIdentifier + let roomProxy: JoinedRoomProxyProtocol + let userIndicatorController: UserIndicatorControllerProtocol +} + +enum ResolveVerifiedUserSendFailureScreenCoordinatorAction { + case dismiss +} + +final class ResolveVerifiedUserSendFailureScreenCoordinator: CoordinatorProtocol { + private let parameters: ResolveVerifiedUserSendFailureScreenCoordinatorParameters + private let viewModel: ResolveVerifiedUserSendFailureScreenViewModelProtocol + + private var cancellables = Set() + + private let actionsSubject: PassthroughSubject = .init() + var actionsPublisher: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + init(parameters: ResolveVerifiedUserSendFailureScreenCoordinatorParameters) { + self.parameters = parameters + + viewModel = ResolveVerifiedUserSendFailureScreenViewModel(failure: parameters.failure, + itemID: parameters.itemID, + roomProxy: parameters.roomProxy, + userIndicatorController: parameters.userIndicatorController) + } + + func start() { + viewModel.actionsPublisher.sink { [weak self] action in + MXLog.info("Coordinator: received view model action: \(action)") + + guard let self else { return } + switch action { + case .dismiss: + actionsSubject.send(.dismiss) + } + } + .store(in: &cancellables) + } + + func toPresentable() -> AnyView { + AnyView(ResolveVerifiedUserSendFailureScreen(context: viewModel.context)) + } +} diff --git a/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/ResolveVerifiedUserSendFailureScreenModels.swift b/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/ResolveVerifiedUserSendFailureScreenModels.swift new file mode 100644 index 0000000000..333d727bd3 --- /dev/null +++ b/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/ResolveVerifiedUserSendFailureScreenModels.swift @@ -0,0 +1,58 @@ +// +// Copyright 2022 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +enum ResolveVerifiedUserSendFailureScreenViewModelAction { + case dismiss +} + +struct ResolveVerifiedUserSendFailureScreenViewState: BindableState { + var currentFailure: TimelineItemSendFailure.VerifiedUser + var currentMemberDisplayName: String + var isYou: Bool + + var title: String { + switch currentFailure { + case .hasUnsignedDevice: + isYou ? L10n.screenResolveSendFailureYouUnsignedDeviceTitle : L10n.screenResolveSendFailureUnsignedDeviceTitle(currentMemberDisplayName) + case .changedIdentity: + L10n.screenResolveSendFailureChangedIdentityTitle(currentMemberDisplayName) + } + } + + var subtitle: String { + switch currentFailure { + case .hasUnsignedDevice: + isYou ? L10n.screenResolveSendFailureYouUnsignedDeviceSubtitle : L10n.screenResolveSendFailureUnsignedDeviceSubtitle(currentMemberDisplayName, currentMemberDisplayName) + case .changedIdentity: + L10n.screenResolveSendFailureChangedIdentitySubtitle(currentMemberDisplayName) + } + } + + var primaryButtonTitle: String { + switch currentFailure { + case .hasUnsignedDevice: L10n.screenResolveSendFailureUnsignedDevicePrimaryButtonTitle + case .changedIdentity: L10n.screenResolveSendFailureChangedIdentityPrimaryButtonTitle + } + } +} + +enum ResolveVerifiedUserSendFailureScreenViewAction { + case resolveAndResend + case resend + case cancel +} diff --git a/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/ResolveVerifiedUserSendFailureScreenViewModel.swift b/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/ResolveVerifiedUserSendFailureScreenViewModel.swift new file mode 100644 index 0000000000..58b60a5aae --- /dev/null +++ b/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/ResolveVerifiedUserSendFailureScreenViewModel.swift @@ -0,0 +1,151 @@ +// +// Copyright 2022 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Combine +import SwiftUI + +typealias ResolveVerifiedUserSendFailureScreenViewModelType = StateStoreViewModel + +class ResolveVerifiedUserSendFailureScreenViewModel: ResolveVerifiedUserSendFailureScreenViewModelType, ResolveVerifiedUserSendFailureScreenViewModelProtocol { + private let iterator: VerifiedUserSendFailureIterator + private let failure: TimelineItemSendFailure.VerifiedUser + private let itemID: TimelineItemIdentifier + private let roomProxy: JoinedRoomProxyProtocol + private var members: [String: RoomMemberProxyProtocol] + + private let userIndicatorController: UserIndicatorControllerProtocol + + private let actionsSubject: PassthroughSubject = .init() + var actionsPublisher: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + init(failure: TimelineItemSendFailure.VerifiedUser, + itemID: TimelineItemIdentifier, + roomProxy: JoinedRoomProxyProtocol, + userIndicatorController: UserIndicatorControllerProtocol) { + iterator = switch failure { + case .hasUnsignedDevice(let devices): UnsignedDeviceFailureIterator(devices: devices) + case .changedIdentity(let users): ChangedIdentityFailureIterator(users: users) + } + + self.failure = failure + self.itemID = itemID + self.roomProxy = roomProxy + self.userIndicatorController = userIndicatorController + + members = Dictionary(uniqueKeysWithValues: roomProxy.membersPublisher.value.map { ($0.userID, $0) }) + + guard let (userID, failure) = iterator.next() else { + MXLog.error("There aren't any known users/devices to resolve the failure with.") + fatalError("There aren't any known users/devices to resolve the failure with.") + } + + super.init(initialViewState: ResolveVerifiedUserSendFailureScreenViewState(currentFailure: failure, + currentMemberDisplayName: members[userID]?.displayName ?? userID, + isYou: userID == roomProxy.ownUserID)) + } + + // MARK: Public + + override func process(viewAction: ResolveVerifiedUserSendFailureScreenViewAction) { + MXLog.info("View model: received view action: \(viewAction)") + + switch viewAction { + case .resolveAndResend: + Task { await resolveAndResend() } + case .resend: + Task { await resend() } + case .cancel: + actionsSubject.send(.dismiss) + } + } + + private func resolveAndResend() async { + let result = switch failure { + case .hasUnsignedDevice(let devices): + await roomProxy.ignoreDeviceTrustAndResend(devices: devices, itemID: itemID) + case .changedIdentity(let users): + await roomProxy.withdrawVerificationAndResend(userIDs: users, itemID: itemID) + } + + if case let .failure(error) = result { + MXLog.error("Failed to resolve send failure: \(error)") + showFailureIndicator() + return + } + + if let (userID, failure) = iterator.next() { + state.currentMemberDisplayName = members[userID]?.displayName ?? userID + state.currentFailure = failure + state.isYou = userID == roomProxy.ownUserID + } else { + actionsSubject.send(.dismiss) + } + } + + private func resend() async { + switch await roomProxy.resend(itemID: itemID) { + case .success: + actionsSubject.send(.dismiss) + case .failure(let error): + MXLog.error("Failed to resend message: \(error)") + showFailureIndicator() + } + } + + private static let failureIndicatorIdentifier = "\(ResolveVerifiedUserSendFailureScreenViewModel.self)-Failure" + + private func showFailureIndicator() { + ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(id: Self.failureIndicatorIdentifier, + type: .toast, + title: L10n.errorUnknown, + iconName: "xmark")) + } +} + +// MARK: - Iterators + +@MainActor +private protocol VerifiedUserSendFailureIterator { + func next() -> (userID: String, failure: TimelineItemSendFailure.VerifiedUser)? +} + +private class UnsignedDeviceFailureIterator: VerifiedUserSendFailureIterator { + private var iterator: [String: [String]].Iterator + + init(devices: [String: [String]]) { + iterator = devices.makeIterator() + } + + func next() -> (userID: String, failure: TimelineItemSendFailure.VerifiedUser)? { + guard let nextUserDevices = iterator.next() else { return nil } + return (nextUserDevices.key, .hasUnsignedDevice(devices: [nextUserDevices.key: nextUserDevices.value])) + } +} + +private class ChangedIdentityFailureIterator: VerifiedUserSendFailureIterator { + private var iterator: [String].Iterator + + init(users: [String]) { + iterator = users.makeIterator() + } + + func next() -> (userID: String, failure: TimelineItemSendFailure.VerifiedUser)? { + guard let nextUserID = iterator.next() else { return nil } + return (nextUserID, .changedIdentity(users: [nextUserID])) + } +} diff --git a/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/ResolveVerifiedUserSendFailureScreenViewModelProtocol.swift b/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/ResolveVerifiedUserSendFailureScreenViewModelProtocol.swift new file mode 100644 index 0000000000..2bdc7bb557 --- /dev/null +++ b/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/ResolveVerifiedUserSendFailureScreenViewModelProtocol.swift @@ -0,0 +1,23 @@ +// +// Copyright 2022 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Combine + +@MainActor +protocol ResolveVerifiedUserSendFailureScreenViewModelProtocol { + var actionsPublisher: AnyPublisher { get } + var context: ResolveVerifiedUserSendFailureScreenViewModelType.Context { get } +} diff --git a/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/View/ResolveVerifiedUserSendFailureScreen.swift b/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/View/ResolveVerifiedUserSendFailureScreen.swift new file mode 100644 index 0000000000..2d2df80a60 --- /dev/null +++ b/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/View/ResolveVerifiedUserSendFailureScreen.swift @@ -0,0 +1,116 @@ +// +// Copyright 2022 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Compound +import SwiftUI + +struct ResolveVerifiedUserSendFailureScreen: View { + @ObservedObject var context: ResolveVerifiedUserSendFailureScreenViewModel.Context + @State private var sheetFrame: CGRect = .zero + + var body: some View { + ScrollView { + VStack(spacing: 40) { + header + buttons + } + .padding(.top, 24) + .padding(.bottom, 16) + .padding(.horizontal, 16) + .readFrame($sheetFrame) + } + .scrollBounceBehavior(.basedOnSize) + .presentationDetents([.height(sheetFrame.height)]) + } + + var header: some View { + VStack(spacing: 8) { + HeroImage(icon: \.error, style: .critical) + .padding(.bottom, 8) + + Text(context.viewState.title) + .font(.compound.headingMDBold) + .multilineTextAlignment(.center) + .foregroundColor(.compound.textPrimary) + + Text(context.viewState.subtitle) + .font(.compound.bodyMD) + .multilineTextAlignment(.center) + .foregroundColor(.compound.textSecondary) + } + } + + var buttons: some View { + VStack(spacing: 16) { + Button(context.viewState.primaryButtonTitle) { + context.send(viewAction: .resolveAndResend) + } + .buttonStyle(.compound(.primary)) + + Button(L10n.actionRetry) { + context.send(viewAction: .resend) + } + .buttonStyle(.compound(.secondary)) + + Button { context.send(viewAction: .cancel) } label: { + Text(L10n.actionCancelForNow) + .padding(.vertical, 14) + } + .buttonStyle(.compound(.plain)) + } + } +} + +// MARK: - Previews + +struct ResolveVerifiedUserSendFailureScreen_Previews: PreviewProvider, TestablePreview { + static let unsignedDeviceViewModel = makeViewModel(failure: .hasUnsignedDevice(devices: ["@alice:matrix.org": []])) + static let ownUnsignedDeviceViewModel = makeViewModel(failure: .hasUnsignedDevice(devices: [RoomMemberProxyMock.mockMe.userID: []])) + static let changedIdentityViewModel = makeViewModel(failure: .changedIdentity(users: ["@alice:matrix.org"])) + + static var previews: some View { + ResolveVerifiedUserSendFailureScreen(context: unsignedDeviceViewModel.context) + .previewDisplayName("Unsigned Device") + + ResolveVerifiedUserSendFailureScreen(context: ownUnsignedDeviceViewModel.context) + .previewDisplayName("Own Unsigned Device") + + ResolveVerifiedUserSendFailureScreen(context: changedIdentityViewModel.context) + .previewDisplayName("Identity Changed") + } + + static func makeViewModel(failure: TimelineItemSendFailure.VerifiedUser) -> ResolveVerifiedUserSendFailureScreenViewModel { + ResolveVerifiedUserSendFailureScreenViewModel(failure: failure, + itemID: .random, + roomProxy: JoinedRoomProxyMock(.init()), + userIndicatorController: UserIndicatorControllerMock()) + } +} + +struct ResolveVerifiedUserSendFailureScreenSheet_Previews: PreviewProvider { + static let viewModel = ResolveVerifiedUserSendFailureScreenViewModel(failure: .changedIdentity(users: ["@alice:matrix.org"]), + itemID: .random, + roomProxy: JoinedRoomProxyMock(.init()), + userIndicatorController: UserIndicatorControllerMock()) + + static var previews: some View { + Text("Hello") + .sheet(isPresented: .constant(true)) { + ResolveVerifiedUserSendFailureScreen(context: viewModel.context) + } + .previewDisplayName("Sheet") + } +} diff --git a/ElementX/Sources/Screens/RoomChangePermissionsScreen/RoomChangePermissionsScreenCoordinator.swift b/ElementX/Sources/Screens/RoomChangePermissionsScreen/RoomChangePermissionsScreenCoordinator.swift index 2ceb155307..596b8eaa8a 100644 --- a/ElementX/Sources/Screens/RoomChangePermissionsScreen/RoomChangePermissionsScreenCoordinator.swift +++ b/ElementX/Sources/Screens/RoomChangePermissionsScreen/RoomChangePermissionsScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -20,7 +11,7 @@ import SwiftUI struct RoomChangePermissionsScreenCoordinatorParameters { let permissions: RoomPermissions let permissionsGroup: RoomRolesAndPermissionsScreenPermissionsGroup - let roomProxy: RoomProxyProtocol + let roomProxy: JoinedRoomProxyProtocol let userIndicatorController: UserIndicatorControllerProtocol let analytics: AnalyticsService } diff --git a/ElementX/Sources/Screens/RoomChangePermissionsScreen/RoomChangePermissionsScreenModels.swift b/ElementX/Sources/Screens/RoomChangePermissionsScreen/RoomChangePermissionsScreenModels.swift index 24a3d56873..2d6692d0a0 100644 --- a/ElementX/Sources/Screens/RoomChangePermissionsScreen/RoomChangePermissionsScreenModels.swift +++ b/ElementX/Sources/Screens/RoomChangePermissionsScreen/RoomChangePermissionsScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/RoomChangePermissionsScreen/RoomChangePermissionsScreenViewModel.swift b/ElementX/Sources/Screens/RoomChangePermissionsScreen/RoomChangePermissionsScreenViewModel.swift index b377cf922f..88b3b5f607 100644 --- a/ElementX/Sources/Screens/RoomChangePermissionsScreen/RoomChangePermissionsScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomChangePermissionsScreen/RoomChangePermissionsScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -21,7 +12,7 @@ import SwiftUI typealias RoomChangePermissionsScreenViewModelType = StateStoreViewModel class RoomChangePermissionsScreenViewModel: RoomChangePermissionsScreenViewModelType, RoomChangePermissionsScreenViewModelProtocol { - private let roomProxy: RoomProxyProtocol + private let roomProxy: JoinedRoomProxyProtocol private let userIndicatorController: UserIndicatorControllerProtocol private let analytics: AnalyticsService @@ -32,7 +23,7 @@ class RoomChangePermissionsScreenViewModel: RoomChangePermissionsScreenViewModel init(currentPermissions: RoomPermissions, group: RoomRolesAndPermissionsScreenPermissionsGroup, - roomProxy: RoomProxyProtocol, + roomProxy: JoinedRoomProxyProtocol, userIndicatorController: UserIndicatorControllerProtocol, analytics: AnalyticsService) { self.roomProxy = roomProxy diff --git a/ElementX/Sources/Screens/RoomChangePermissionsScreen/RoomChangePermissionsScreenViewModelProtocol.swift b/ElementX/Sources/Screens/RoomChangePermissionsScreen/RoomChangePermissionsScreenViewModelProtocol.swift index 33c6cf6bd5..b2eb8346d3 100644 --- a/ElementX/Sources/Screens/RoomChangePermissionsScreen/RoomChangePermissionsScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/RoomChangePermissionsScreen/RoomChangePermissionsScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/RoomChangePermissionsScreen/View/RoomChangePermissionsScreen.swift b/ElementX/Sources/Screens/RoomChangePermissionsScreen/View/RoomChangePermissionsScreen.swift index b89e2fa85c..75edd5985b 100644 --- a/ElementX/Sources/Screens/RoomChangePermissionsScreen/View/RoomChangePermissionsScreen.swift +++ b/ElementX/Sources/Screens/RoomChangePermissionsScreen/View/RoomChangePermissionsScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -86,7 +77,7 @@ struct RoomChangePermissionsScreen_Previews: PreviewProvider, TestablePreview { static func makeViewModel(group: RoomRolesAndPermissionsScreenPermissionsGroup) -> RoomChangePermissionsScreenViewModel { RoomChangePermissionsScreenViewModel(currentPermissions: .init(powerLevels: .mock), group: group, - roomProxy: RoomProxyMock(.init()), + roomProxy: JoinedRoomProxyMock(.init()), userIndicatorController: UserIndicatorControllerMock(), analytics: ServiceLocator.shared.analytics) } diff --git a/ElementX/Sources/Screens/RoomChangeRolesScreen/RoomChangeRolesScreenCoordinator.swift b/ElementX/Sources/Screens/RoomChangeRolesScreen/RoomChangeRolesScreenCoordinator.swift index 854fd66399..54064de2f4 100644 --- a/ElementX/Sources/Screens/RoomChangeRolesScreen/RoomChangeRolesScreenCoordinator.swift +++ b/ElementX/Sources/Screens/RoomChangeRolesScreen/RoomChangeRolesScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -19,7 +10,7 @@ import SwiftUI struct RoomChangeRolesScreenCoordinatorParameters { let mode: RoomMemberDetails.Role - let roomProxy: RoomProxyProtocol + let roomProxy: JoinedRoomProxyProtocol let mediaProvider: MediaProviderProtocol let userIndicatorController: UserIndicatorControllerProtocol let analytics: AnalyticsService diff --git a/ElementX/Sources/Screens/RoomChangeRolesScreen/RoomChangeRolesScreenModels.swift b/ElementX/Sources/Screens/RoomChangeRolesScreen/RoomChangeRolesScreenModels.swift index 53b851fdb7..1600f5d75b 100644 --- a/ElementX/Sources/Screens/RoomChangeRolesScreen/RoomChangeRolesScreenModels.swift +++ b/ElementX/Sources/Screens/RoomChangeRolesScreen/RoomChangeRolesScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Collections diff --git a/ElementX/Sources/Screens/RoomChangeRolesScreen/RoomChangeRolesScreenViewModel.swift b/ElementX/Sources/Screens/RoomChangeRolesScreen/RoomChangeRolesScreenViewModel.swift index c86303f4d3..984ce6cfea 100644 --- a/ElementX/Sources/Screens/RoomChangeRolesScreen/RoomChangeRolesScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomChangeRolesScreen/RoomChangeRolesScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -20,7 +11,7 @@ import SwiftUI typealias RoomChangeRolesScreenViewModelType = StateStoreViewModel class RoomChangeRolesScreenViewModel: RoomChangeRolesScreenViewModelType, RoomChangeRolesScreenViewModelProtocol { - private let roomProxy: RoomProxyProtocol + private let roomProxy: JoinedRoomProxyProtocol private let userIndicatorController: UserIndicatorControllerProtocol private let analytics: AnalyticsService @@ -30,7 +21,7 @@ class RoomChangeRolesScreenViewModel: RoomChangeRolesScreenViewModelType, RoomCh } init(mode: RoomMemberDetails.Role, - roomProxy: RoomProxyProtocol, + roomProxy: JoinedRoomProxyProtocol, mediaProvider: MediaProviderProtocol, userIndicatorController: UserIndicatorControllerProtocol, analytics: AnalyticsService) { @@ -45,7 +36,7 @@ class RoomChangeRolesScreenViewModel: RoomChangeRolesScreenViewModelType, RoomCh moderators: [], users: [], bindings: .init()), - imageProvider: mediaProvider) + mediaProvider: mediaProvider) roomProxy.membersPublisher .receive(on: DispatchQueue.main) diff --git a/ElementX/Sources/Screens/RoomChangeRolesScreen/RoomChangeRolesScreenViewModelProtocol.swift b/ElementX/Sources/Screens/RoomChangeRolesScreen/RoomChangeRolesScreenViewModelProtocol.swift index 5c46963d29..d045174f92 100644 --- a/ElementX/Sources/Screens/RoomChangeRolesScreen/RoomChangeRolesScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/RoomChangeRolesScreen/RoomChangeRolesScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/RoomChangeRolesScreen/View/RoomChangeRolesScreen.swift b/ElementX/Sources/Screens/RoomChangeRolesScreen/View/RoomChangeRolesScreen.swift index 734868eae3..54c328e73f 100644 --- a/ElementX/Sources/Screens/RoomChangeRolesScreen/View/RoomChangeRolesScreen.swift +++ b/ElementX/Sources/Screens/RoomChangeRolesScreen/View/RoomChangeRolesScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -74,7 +65,7 @@ struct RoomChangeRolesScreen: View { ScrollViewReader { scrollView in HStack(spacing: 16) { ForEach(context.viewState.membersWithRole, id: \.id) { member in - RoomChangeRolesScreenSelectedItem(member: member, imageProvider: context.imageProvider) { + RoomChangeRolesScreenSelectedItem(member: member, mediaProvider: context.mediaProvider) { context.send(viewAction: .demoteMember(member)) } .frame(width: cellWidth) @@ -130,7 +121,7 @@ struct RoomChangeRolesScreen_Previews: PreviewProvider, TestablePreview { static func makeViewModel(mode: RoomMemberDetails.Role) -> RoomChangeRolesScreenViewModel { RoomChangeRolesScreenViewModel(mode: mode, - roomProxy: RoomProxyMock(.init(members: .allMembersAsAdmin)), + roomProxy: JoinedRoomProxyMock(.init(members: .allMembersAsAdmin)), mediaProvider: MockMediaProvider(), userIndicatorController: UserIndicatorControllerMock(), analytics: ServiceLocator.shared.analytics) diff --git a/ElementX/Sources/Screens/RoomChangeRolesScreen/View/RoomChangeRolesScreenRow.swift b/ElementX/Sources/Screens/RoomChangeRolesScreen/View/RoomChangeRolesScreenRow.swift index 6048a22cbe..d9cec3331e 100644 --- a/ElementX/Sources/Screens/RoomChangeRolesScreen/View/RoomChangeRolesScreenRow.swift +++ b/ElementX/Sources/Screens/RoomChangeRolesScreen/View/RoomChangeRolesScreenRow.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -20,7 +11,7 @@ import SwiftUI struct RoomChangeRolesScreenRow: View { let member: RoomMemberDetails - let imageProvider: ImageProviderProtocol? + let mediaProvider: MediaProviderProtocol? let isSelected: Bool let action: () -> Void @@ -38,7 +29,7 @@ struct RoomChangeRolesScreenRow: View { name: member.name, contentID: member.id, avatarSize: .user(on: .startChat), - imageProvider: imageProvider) + mediaProvider: mediaProvider) } } @@ -48,34 +39,34 @@ struct RoomChangeRolesScreenRow_Previews: PreviewProvider, TestablePreview { static var previews: some View { Form { RoomChangeRolesScreenRow(member: .init(withProxy: RoomMemberProxyMock.mockAlice), - imageProvider: MockMediaProvider(), + mediaProvider: MockMediaProvider(), isSelected: true, action: action) RoomChangeRolesScreenRow(member: .init(withProxy: RoomMemberProxyMock.mockBob), - imageProvider: MockMediaProvider(), + mediaProvider: MockMediaProvider(), isSelected: false, action: action) RoomChangeRolesScreenRow(member: .init(withProxy: RoomMemberProxyMock.mockInvited), - imageProvider: MockMediaProvider(), + mediaProvider: MockMediaProvider(), isSelected: false, action: action) RoomChangeRolesScreenRow(member: .init(withProxy: RoomMemberProxyMock.mockCharlie), - imageProvider: MockMediaProvider(), + mediaProvider: MockMediaProvider(), isSelected: true, action: action) .disabled(true) RoomChangeRolesScreenRow(member: .init(withProxy: RoomMemberProxyMock(with: .init(userID: "@someone:matrix.org", membership: .join))), - imageProvider: MockMediaProvider(), + mediaProvider: MockMediaProvider(), isSelected: false, action: action) .disabled(true) RoomChangeRolesScreenRow(member: .init(withProxy: RoomMemberProxyMock(with: .init(userID: "@someone:matrix.org", membership: .join))), - imageProvider: MockMediaProvider(), + mediaProvider: MockMediaProvider(), isSelected: false, action: action) } diff --git a/ElementX/Sources/Screens/RoomChangeRolesScreen/View/RoomChangeRolesScreenSection.swift b/ElementX/Sources/Screens/RoomChangeRolesScreen/View/RoomChangeRolesScreenSection.swift index b2a06ffeed..b315e6f798 100644 --- a/ElementX/Sources/Screens/RoomChangeRolesScreen/View/RoomChangeRolesScreenSection.swift +++ b/ElementX/Sources/Screens/RoomChangeRolesScreen/View/RoomChangeRolesScreenSection.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -29,7 +20,7 @@ struct RoomChangeRolesScreenSection: View { Section { ForEach(members, id: \.id) { member in RoomChangeRolesScreenRow(member: member, - imageProvider: context.imageProvider, + mediaProvider: context.mediaProvider, isSelected: isMemberSelected(member)) { context.send(viewAction: .toggleMember(member)) } diff --git a/ElementX/Sources/Screens/RoomChangeRolesScreen/View/RoomChangeRolesScreenSelectedItem.swift b/ElementX/Sources/Screens/RoomChangeRolesScreen/View/RoomChangeRolesScreenSelectedItem.swift index 4625907872..dbbe1d5d5b 100644 --- a/ElementX/Sources/Screens/RoomChangeRolesScreen/View/RoomChangeRolesScreenSelectedItem.swift +++ b/ElementX/Sources/Screens/RoomChangeRolesScreen/View/RoomChangeRolesScreenSelectedItem.swift @@ -1,24 +1,15 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI struct RoomChangeRolesScreenSelectedItem: View { let member: RoomMemberDetails - let imageProvider: ImageProviderProtocol? + let mediaProvider: MediaProviderProtocol? let dismissAction: () -> Void var body: some View { @@ -39,7 +30,7 @@ struct RoomChangeRolesScreenSelectedItem: View { name: member.name, contentID: member.id, avatarSize: .user(on: .inviteUsers), - imageProvider: imageProvider) + mediaProvider: mediaProvider) .overlay(alignment: .topTrailing) { if member.role != .administrator { Button(action: dismissAction) { @@ -69,7 +60,7 @@ struct RoomChangeRolesScreenSelectedItem_Previews: PreviewProvider, TestablePrev HStack(spacing: 12) { ForEach(members, id: \.id) { member in RoomChangeRolesScreenSelectedItem(member: member, - imageProvider: MockMediaProvider(), + mediaProvider: MockMediaProvider(), dismissAction: { }) .frame(width: 72) } diff --git a/ElementX/Sources/Screens/RoomDetailsEditScreen/RoomDetailsEditScreenCoordinator.swift b/ElementX/Sources/Screens/RoomDetailsEditScreen/RoomDetailsEditScreenCoordinator.swift index 11d9a74e35..0bec89382e 100644 --- a/ElementX/Sources/Screens/RoomDetailsEditScreen/RoomDetailsEditScreenCoordinator.swift +++ b/ElementX/Sources/Screens/RoomDetailsEditScreen/RoomDetailsEditScreenCoordinator.swift @@ -1,24 +1,15 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine import SwiftUI struct RoomDetailsEditScreenCoordinatorParameters { - let roomProxy: RoomProxyProtocol + let roomProxy: JoinedRoomProxyProtocol let mediaProvider: MediaProviderProtocol weak var navigationStackCoordinator: NavigationStackCoordinator? let userIndicatorController: UserIndicatorControllerProtocol diff --git a/ElementX/Sources/Screens/RoomDetailsEditScreen/RoomDetailsEditScreenModels.swift b/ElementX/Sources/Screens/RoomDetailsEditScreen/RoomDetailsEditScreenModels.swift index 29f1365669..1a5b6a8328 100644 --- a/ElementX/Sources/Screens/RoomDetailsEditScreen/RoomDetailsEditScreenModels.swift +++ b/ElementX/Sources/Screens/RoomDetailsEditScreen/RoomDetailsEditScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/RoomDetailsEditScreen/RoomDetailsEditScreenViewModel.swift b/ElementX/Sources/Screens/RoomDetailsEditScreen/RoomDetailsEditScreenViewModel.swift index abbef093c3..26fa1f0a26 100644 --- a/ElementX/Sources/Screens/RoomDetailsEditScreen/RoomDetailsEditScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomDetailsEditScreen/RoomDetailsEditScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -21,7 +12,7 @@ typealias RoomDetailsEditScreenViewModelType = StateStoreViewModel = .init() - private let roomProxy: RoomProxyProtocol + private let roomProxy: JoinedRoomProxyProtocol private let userIndicatorController: UserIndicatorControllerProtocol private let mediaPreprocessor: MediaUploadingPreprocessor = .init() @@ -29,7 +20,7 @@ class RoomDetailsEditScreenViewModel: RoomDetailsEditScreenViewModelType, RoomDe actionsSubject.eraseToAnyPublisher() } - init(roomProxy: RoomProxyProtocol, + init(roomProxy: JoinedRoomProxyProtocol, mediaProvider: MediaProviderProtocol, userIndicatorController: UserIndicatorControllerProtocol) { self.roomProxy = roomProxy @@ -44,7 +35,7 @@ class RoomDetailsEditScreenViewModel: RoomDetailsEditScreenViewModelType, RoomDe initialName: roomName ?? "", initialTopic: roomTopic ?? "", avatarURL: roomAvatar, - bindings: .init(name: roomName ?? "", topic: roomTopic ?? "")), imageProvider: mediaProvider) + bindings: .init(name: roomName ?? "", topic: roomTopic ?? "")), mediaProvider: mediaProvider) Task { // Can't use async let because the mocks aren't thread safe when calling the same method ๐Ÿคฆโ€โ™‚๏ธ diff --git a/ElementX/Sources/Screens/RoomDetailsEditScreen/RoomDetailsEditScreenViewModelProtocol.swift b/ElementX/Sources/Screens/RoomDetailsEditScreen/RoomDetailsEditScreenViewModelProtocol.swift index 04adc04386..440123025d 100644 --- a/ElementX/Sources/Screens/RoomDetailsEditScreen/RoomDetailsEditScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/RoomDetailsEditScreen/RoomDetailsEditScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/RoomDetailsEditScreen/View/RoomDetailsEditScreen.swift b/ElementX/Sources/Screens/RoomDetailsEditScreen/View/RoomDetailsEditScreen.swift index 4266bb808a..db4a1c6abc 100644 --- a/ElementX/Sources/Screens/RoomDetailsEditScreen/View/RoomDetailsEditScreen.swift +++ b/ElementX/Sources/Screens/RoomDetailsEditScreen/View/RoomDetailsEditScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -68,7 +59,7 @@ struct RoomDetailsEditScreen: View { name: context.viewState.initialName, contentID: context.viewState.roomID, avatarSize: .user(on: .memberDetails), - imageProvider: context.imageProvider) + mediaProvider: context.mediaProvider) .overlay(alignment: .bottomTrailing) { if context.viewState.canEditAvatar { avatarOverlayIcon @@ -157,9 +148,9 @@ struct RoomDetailsEditScreen: View { struct RoomDetailsEditScreen_Previews: PreviewProvider, TestablePreview { static let editableViewModel = { - let roomProxy = RoomProxyMock(.init(id: "test_id", - name: "Room", - members: [.mockMeAdmin])) + let roomProxy = JoinedRoomProxyMock(.init(id: "test_id", + name: "Room", + members: [.mockMeAdmin])) return RoomDetailsEditScreenViewModel(roomProxy: roomProxy, mediaProvider: MockMediaProvider(), @@ -167,9 +158,9 @@ struct RoomDetailsEditScreen_Previews: PreviewProvider, TestablePreview { }() static let readOnlyViewModel = { - let roomProxy = RoomProxyMock(.init(id: "test_id", - name: "Room", - members: [.mockAlice])) + let roomProxy = JoinedRoomProxyMock(.init(id: "test_id", + name: "Room", + members: [.mockAlice])) return RoomDetailsEditScreenViewModel(roomProxy: roomProxy, mediaProvider: MockMediaProvider(), @@ -181,12 +172,12 @@ struct RoomDetailsEditScreen_Previews: PreviewProvider, TestablePreview { RoomDetailsEditScreen(context: readOnlyViewModel.context) } .previewDisplayName("Read only") - .snapshot(delay: 0.25) + .snapshotPreferences(delay: 0.25) NavigationStack { RoomDetailsEditScreen(context: editableViewModel.context) } .previewDisplayName("Editable") - .snapshot(delay: 0.25) + .snapshotPreferences(delay: 0.25) } } diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenCoordinator.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenCoordinator.swift index 5a430f3e60..92dbcc3b42 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenCoordinator.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenCoordinator.swift @@ -1,24 +1,15 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine import SwiftUI struct RoomDetailsScreenCoordinatorParameters { - let roomProxy: RoomProxyProtocol + let roomProxy: JoinedRoomProxyProtocol let clientProxy: ClientProxyProtocol let mediaProvider: MediaProviderProtocol let analyticsService: AnalyticsService diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift index 4280155251..77a328956f 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift index dc40f316a3..79e83484e2 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -20,7 +11,7 @@ import SwiftUI typealias RoomDetailsScreenViewModelType = StateStoreViewModel class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScreenViewModelProtocol { - private let roomProxy: RoomProxyProtocol + private let roomProxy: JoinedRoomProxyProtocol private let clientProxy: ClientProxyProtocol private let analyticsService: AnalyticsService private let mediaProvider: MediaProviderProtocol @@ -54,7 +45,7 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr actionsSubject.eraseToAnyPublisher() } - init(roomProxy: RoomProxyProtocol, + init(roomProxy: JoinedRoomProxyProtocol, clientProxy: ClientProxyProtocol, mediaProvider: MediaProviderProtocol, analyticsService: AnalyticsService, @@ -82,7 +73,7 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr joinedMembersCount: roomProxy.joinedMembersCount, notificationSettingsState: .loading, bindings: .init()), - imageProvider: mediaProvider) + mediaProvider: mediaProvider) appSettings.$pinningEnabled .weakAssign(to: \.state.isPinningEnabled, on: self) @@ -170,6 +161,7 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr case .processTapCall: actionsSubject.send(.startCall) case .processTapPinnedEvents: + analyticsService.trackInteraction(name: .PinnedMessageRoomInfoButton) actionsSubject.send(.displayPinnedEventsTimeline) } } diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModelProtocol.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModelProtocol.swift index bafd1543e3..bc26f89143 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift index bae61abeec..73a8446f98 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -66,7 +57,7 @@ struct RoomDetailsScreen: View { .navigationTitle(L10n.screenRoomDetailsTitle) .navigationBarTitleDisplayMode(.inline) .track(screen: .RoomDetails) - .interactiveQuickLook(item: $context.mediaPreviewItem, shouldHideControls: true) + .interactiveQuickLook(item: $context.mediaPreviewItem, allowEditing: false) } // MARK: - Private @@ -74,7 +65,7 @@ struct RoomDetailsScreen: View { private var normalRoomHeaderSection: some View { AvatarHeaderView(room: context.viewState.details, avatarSize: .room(on: .details), - imageProvider: context.imageProvider) { + mediaProvider: context.mediaProvider) { context.send(viewAction: .displayAvatar) } footer: { if !context.viewState.shortcuts.isEmpty { @@ -87,7 +78,7 @@ struct RoomDetailsScreen: View { private func dmHeaderSection(accountOwner: RoomMemberDetails, recipient: RoomMemberDetails) -> some View { AvatarHeaderView(accountOwner: accountOwner, dmRecipient: recipient, - imageProvider: context.imageProvider) { + mediaProvider: context.mediaProvider) { context.send(viewAction: .displayAvatar) } footer: { if !context.viewState.shortcuts.isEmpty { @@ -311,20 +302,20 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview { .mockBob, .mockCharlie ] - let roomProxy = RoomProxyMock(.init(id: "room_a_id", - name: "Room A", - topic: """ - Discussions about Element X iOS | https://github.com/vector-im/element-x-ios - - Feature Status: https://github.com/vector-im/element-x-ios/issues/1225 - - App Store: https://apple.co/3r6LJHZ - TestFlight: https://testflight.apple.com/join/uZbeZCOi - """, - isDirect: false, - isEncrypted: true, - canonicalAlias: "#alias:domain.com", - members: members)) + let roomProxy = JoinedRoomProxyMock(.init(id: "room_a_id", + name: "Room A", + topic: """ + Discussions about Element X iOS | https://github.com/vector-im/element-x-ios + + Feature Status: https://github.com/vector-im/element-x-ios/issues/1225 + + App Store: https://apple.co/3r6LJHZ + TestFlight: https://testflight.apple.com/join/uZbeZCOi + """, + isDirect: false, + isEncrypted: true, + canonicalAlias: "#alias:domain.com", + members: members)) var notificationSettingsProxyMockConfiguration = NotificationSettingsProxyMockConfiguration() notificationSettingsProxyMockConfiguration.roomMode.isDefault = false @@ -349,13 +340,13 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview { .mockDan ] - let roomProxy = RoomProxyMock(.init(id: "dm_room_id", - name: "DM Room", - topic: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", - isDirect: true, - isEncrypted: true, - canonicalAlias: "#alias:domain.com", - members: members)) + let roomProxy = JoinedRoomProxyMock(.init(id: "dm_room_id", + name: "DM Room", + topic: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + isDirect: true, + isEncrypted: true, + canonicalAlias: "#alias:domain.com", + members: members)) let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init()) let appSettings = AppSettings() appSettings.pinningEnabled = true @@ -378,11 +369,11 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview { .mockBob, .mockCharlie ] - let roomProxy = RoomProxyMock(.init(id: "simple_room_id", - name: "Room A", - isDirect: false, - isEncrypted: false, - members: members)) + let roomProxy = JoinedRoomProxyMock(.init(id: "simple_room_id", + name: "Room A", + isDirect: false, + isEncrypted: false, + members: members)) let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init()) let appSettings = AppSettings() appSettings.pinningEnabled = true @@ -401,12 +392,12 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview { static var previews: some View { RoomDetailsScreen(context: simpleRoomViewModel.context) .previewDisplayName("Simple Room") - .snapshot(delay: 2) + .snapshotPreferences(delay: 2) RoomDetailsScreen(context: dmRoomViewModel.context) .previewDisplayName("DM Room") - .snapshot(delay: 0.25) + .snapshotPreferences(delay: 0.25) RoomDetailsScreen(context: genericRoomViewModel.context) .previewDisplayName("Generic Room") - .snapshot(delay: 0.25) + .snapshotPreferences(delay: 0.25) } } diff --git a/ElementX/Sources/Screens/RoomDirectorySearchScreen/RoomDirectorySearchScreenCoordinator.swift b/ElementX/Sources/Screens/RoomDirectorySearchScreen/RoomDirectorySearchScreenCoordinator.swift index 3c56efe335..e83eb8718b 100644 --- a/ElementX/Sources/Screens/RoomDirectorySearchScreen/RoomDirectorySearchScreenCoordinator.swift +++ b/ElementX/Sources/Screens/RoomDirectorySearchScreen/RoomDirectorySearchScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -19,7 +10,7 @@ import SwiftUI struct RoomDirectorySearchScreenCoordinatorParameters { let clientProxy: ClientProxyProtocol - let imageProvider: ImageProviderProtocol + let mediaProvider: MediaProviderProtocol let userIndicatorController: UserIndicatorControllerProtocol } @@ -42,7 +33,7 @@ final class RoomDirectorySearchScreenCoordinator: CoordinatorProtocol { init(parameters: RoomDirectorySearchScreenCoordinatorParameters) { viewModel = RoomDirectorySearchScreenViewModel(clientProxy: parameters.clientProxy, userIndicatorController: parameters.userIndicatorController, - imageProvider: parameters.imageProvider) + mediaProvider: parameters.mediaProvider) } func start() { diff --git a/ElementX/Sources/Screens/RoomDirectorySearchScreen/RoomDirectorySearchScreenModels.swift b/ElementX/Sources/Screens/RoomDirectorySearchScreen/RoomDirectorySearchScreenModels.swift index 6ebae1fa4c..78079d562c 100644 --- a/ElementX/Sources/Screens/RoomDirectorySearchScreen/RoomDirectorySearchScreenModels.swift +++ b/ElementX/Sources/Screens/RoomDirectorySearchScreen/RoomDirectorySearchScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/RoomDirectorySearchScreen/RoomDirectorySearchScreenScreenModelProtocol.swift b/ElementX/Sources/Screens/RoomDirectorySearchScreen/RoomDirectorySearchScreenScreenModelProtocol.swift index 6c209568f5..45b5b92c91 100644 --- a/ElementX/Sources/Screens/RoomDirectorySearchScreen/RoomDirectorySearchScreenScreenModelProtocol.swift +++ b/ElementX/Sources/Screens/RoomDirectorySearchScreen/RoomDirectorySearchScreenScreenModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/RoomDirectorySearchScreen/RoomDirectorySearchScreenViewModel.swift b/ElementX/Sources/Screens/RoomDirectorySearchScreen/RoomDirectorySearchScreenViewModel.swift index 1e5ebb5578..2a712dfd91 100644 --- a/ElementX/Sources/Screens/RoomDirectorySearchScreen/RoomDirectorySearchScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomDirectorySearchScreen/RoomDirectorySearchScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -30,11 +21,11 @@ class RoomDirectorySearchScreenViewModel: RoomDirectorySearchScreenViewModelType init(clientProxy: ClientProxyProtocol, userIndicatorController: UserIndicatorControllerProtocol, - imageProvider: ImageProviderProtocol) { + mediaProvider: MediaProviderProtocol) { roomDirectorySearchProxy = clientProxy.roomDirectorySearchProxy() self.userIndicatorController = userIndicatorController - super.init(initialViewState: RoomDirectorySearchScreenViewState(), imageProvider: imageProvider) + super.init(initialViewState: RoomDirectorySearchScreenViewState(), mediaProvider: mediaProvider) state.rooms = roomDirectorySearchProxy.resultsPublisher.value diff --git a/ElementX/Sources/Screens/RoomDirectorySearchScreen/View/RoomDirectoryCell.swift b/ElementX/Sources/Screens/RoomDirectorySearchScreen/View/RoomDirectoryCell.swift index 53ca9e5b42..fab1dd568b 100644 --- a/ElementX/Sources/Screens/RoomDirectorySearchScreen/View/RoomDirectoryCell.swift +++ b/ElementX/Sources/Screens/RoomDirectorySearchScreen/View/RoomDirectoryCell.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -19,7 +10,7 @@ import SwiftUI struct RoomDirectorySearchCell: View { let result: RoomDirectorySearchResult - let imageProvider: ImageProviderProtocol? + let mediaProvider: MediaProviderProtocol? let joinAction: () -> Void private var description: String? { @@ -46,7 +37,7 @@ struct RoomDirectorySearchCell: View { private var avatar: some View { RoomAvatarImage(avatar: result.avatar, avatarSize: .room(on: .roomDirectorySearch), - imageProvider: imageProvider) + mediaProvider: mediaProvider) .accessibilityHidden(true) } } @@ -64,7 +55,7 @@ struct RoomDirectorySearchCell_Previews: PreviewProvider, TestablePreview { name: "Test title", avatarURL: nil), canBeJoined: true), - imageProvider: MockMediaProvider()) { } + mediaProvider: MockMediaProvider()) { } RoomDirectorySearchCell(result: .init(id: "!test_id_2:matrix.org", alias: "#test:example.com", @@ -74,7 +65,7 @@ struct RoomDirectorySearchCell_Previews: PreviewProvider, TestablePreview { name: nil, avatarURL: nil), canBeJoined: true), - imageProvider: MockMediaProvider()) { } + mediaProvider: MockMediaProvider()) { } RoomDirectorySearchCell(result: .init(id: "!test_id_3:example.com", alias: "#test_no_topic:example.com", @@ -84,7 +75,7 @@ struct RoomDirectorySearchCell_Previews: PreviewProvider, TestablePreview { name: "Test title no topic", avatarURL: nil), canBeJoined: true), - imageProvider: MockMediaProvider()) { } + mediaProvider: MockMediaProvider()) { } RoomDirectorySearchCell(result: .init(id: "!test_id_4:example.com", alias: "#test_no_topic:example.com", @@ -94,7 +85,7 @@ struct RoomDirectorySearchCell_Previews: PreviewProvider, TestablePreview { name: nil, avatarURL: nil), canBeJoined: true), - imageProvider: MockMediaProvider()) { } + mediaProvider: MockMediaProvider()) { } RoomDirectorySearchCell(result: .init(id: "!test_id_5:example.com", alias: nil, @@ -104,7 +95,7 @@ struct RoomDirectorySearchCell_Previews: PreviewProvider, TestablePreview { name: "Test title no alias", avatarURL: nil), canBeJoined: false), - imageProvider: MockMediaProvider()) { } + mediaProvider: MockMediaProvider()) { } RoomDirectorySearchCell(result: .init(id: "!test_id_6:example.com", alias: nil, @@ -114,7 +105,7 @@ struct RoomDirectorySearchCell_Previews: PreviewProvider, TestablePreview { name: "Test title no alias", avatarURL: nil), canBeJoined: false), - imageProvider: MockMediaProvider()) { } + mediaProvider: MockMediaProvider()) { } RoomDirectorySearchCell(result: .init(id: "!test_id_7:example.com", alias: nil, @@ -124,7 +115,7 @@ struct RoomDirectorySearchCell_Previews: PreviewProvider, TestablePreview { name: nil, avatarURL: nil), canBeJoined: false), - imageProvider: MockMediaProvider()) { } + mediaProvider: MockMediaProvider()) { } RoomDirectorySearchCell(result: .init(id: "!test_id_8:example.com", alias: nil, name: nil, @@ -133,7 +124,7 @@ struct RoomDirectorySearchCell_Previews: PreviewProvider, TestablePreview { name: nil, avatarURL: nil), canBeJoined: false), - imageProvider: MockMediaProvider()) { } + mediaProvider: MockMediaProvider()) { } } .compoundList() } diff --git a/ElementX/Sources/Screens/RoomDirectorySearchScreen/View/RoomDirectorySearchScreen.swift b/ElementX/Sources/Screens/RoomDirectorySearchScreen/View/RoomDirectorySearchScreen.swift index 19b8b395d0..779a312cf7 100644 --- a/ElementX/Sources/Screens/RoomDirectorySearchScreen/View/RoomDirectorySearchScreen.swift +++ b/ElementX/Sources/Screens/RoomDirectorySearchScreen/View/RoomDirectorySearchScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -25,7 +16,7 @@ struct RoomDirectorySearchScreen: View { List { Section { ForEach(context.viewState.rooms) { room in - RoomDirectorySearchCell(result: room, imageProvider: context.imageProvider) { + RoomDirectorySearchCell(result: room, mediaProvider: context.mediaProvider) { context.send(viewAction: .select(room: room)) } } @@ -102,11 +93,11 @@ struct RoomDirectorySearchScreen_Previews: PreviewProvider, TestablePreview { return RoomDirectorySearchScreenViewModel(clientProxy: clientProxy, userIndicatorController: UserIndicatorControllerMock(), - imageProvider: MockMediaProvider()) + mediaProvider: MockMediaProvider()) }() static var previews: some View { RoomDirectorySearchScreen(context: viewModel.context) - .snapshot(delay: 1.0) + .snapshotPreferences(delay: 1.0) } } diff --git a/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenCoordinator.swift b/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenCoordinator.swift index d5c3d5abf0..f57b12228b 100644 --- a/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenCoordinator.swift +++ b/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -19,7 +10,7 @@ import SwiftUI struct RoomMemberDetailsScreenCoordinatorParameters { let userID: String - let roomProxy: RoomProxyProtocol + let roomProxy: JoinedRoomProxyProtocol let clientProxy: ClientProxyProtocol let mediaProvider: MediaProviderProtocol let userIndicatorController: UserIndicatorControllerProtocol diff --git a/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenModels.swift b/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenModels.swift index 9a5c4096d7..fb444c2a10 100644 --- a/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenModels.swift +++ b/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift b/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift index 0592098faf..6249d7da6c 100644 --- a/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -20,7 +11,7 @@ import SwiftUI typealias RoomMemberDetailsScreenViewModelType = StateStoreViewModel class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, RoomMemberDetailsScreenViewModelProtocol { - private let roomProxy: RoomProxyProtocol + private let roomProxy: JoinedRoomProxyProtocol private let clientProxy: ClientProxyProtocol private let mediaProvider: MediaProviderProtocol private let userIndicatorController: UserIndicatorControllerProtocol @@ -35,7 +26,7 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro } init(userID: String, - roomProxy: RoomProxyProtocol, + roomProxy: JoinedRoomProxyProtocol, clientProxy: ClientProxyProtocol, mediaProvider: MediaProviderProtocol, userIndicatorController: UserIndicatorControllerProtocol, @@ -48,7 +39,7 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro let initialViewState = RoomMemberDetailsScreenViewState(userID: userID, bindings: .init()) - super.init(initialViewState: initialViewState, imageProvider: mediaProvider) + super.init(initialViewState: initialViewState, mediaProvider: mediaProvider) showMemberLoadingIndicator() Task { diff --git a/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModelProtocol.swift b/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModelProtocol.swift index e7ee561a61..748f865485 100644 --- a/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift b/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift index b9dae52004..1861cd1deb 100644 --- a/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift +++ b/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -33,7 +24,7 @@ struct RoomMemberDetailsScreen: View { .alert(item: $context.ignoreUserAlert, actions: blockUserAlertActions, message: blockUserAlertMessage) .alert(item: $context.alertInfo) .track(screen: .User) - .interactiveQuickLook(item: $context.mediaPreviewItem, shouldHideControls: true) + .interactiveQuickLook(item: $context.mediaPreviewItem, allowEditing: false) } // MARK: - Private @@ -75,7 +66,7 @@ struct RoomMemberDetailsScreen: View { if let memberDetails = context.viewState.memberDetails { AvatarHeaderView(member: memberDetails, avatarSize: .user(on: .memberDetails), - imageProvider: context.imageProvider) { + mediaProvider: context.mediaProvider) { context.send(viewAction: .displayAvatar) } footer: { otherUserFooter @@ -83,7 +74,7 @@ struct RoomMemberDetailsScreen: View { } else { AvatarHeaderView(user: UserProfileProxy(userID: context.viewState.userID), avatarSize: .user(on: .memberDetails), - imageProvider: context.imageProvider, + mediaProvider: context.mediaProvider, footer: { }) } } @@ -133,17 +124,17 @@ struct RoomMemberDetailsScreen_Previews: PreviewProvider, TestablePreview { static var previews: some View { RoomMemberDetailsScreen(context: otherUserViewModel.context) .previewDisplayName("Other User") - .snapshot(delay: 0.25) + .snapshotPreferences(delay: 0.25) RoomMemberDetailsScreen(context: accountOwnerViewModel.context) .previewDisplayName("Account Owner") - .snapshot(delay: 0.25) + .snapshotPreferences(delay: 0.25) RoomMemberDetailsScreen(context: ignoredUserViewModel.context) .previewDisplayName("Ignored User") - .snapshot(delay: 0.25) + .snapshotPreferences(delay: 0.25) } static func makeViewModel(member: RoomMemberProxyMock) -> RoomMemberDetailsScreenViewModel { - let roomProxyMock = RoomProxyMock(.init(name: "")) + let roomProxyMock = JoinedRoomProxyMock(.init(name: "")) roomProxyMock.getMemberUserIDReturnValue = .success(member) let clientProxyMock = ClientProxyMock(.init()) diff --git a/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenCoordinator.swift b/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenCoordinator.swift index 44fbeaf5c1..f3220a7232 100644 --- a/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenCoordinator.swift +++ b/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -19,7 +10,7 @@ import SwiftUI struct RoomMembersListScreenCoordinatorParameters { let mediaProvider: MediaProviderProtocol - let roomProxy: RoomProxyProtocol + let roomProxy: JoinedRoomProxyProtocol let userIndicatorController: UserIndicatorControllerProtocol let analytics: AnalyticsService } diff --git a/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenModels.swift b/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenModels.swift index e589a17f9a..5ada7af54e 100644 --- a/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenModels.swift +++ b/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenViewModel.swift b/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenViewModel.swift index 605147af27..129b8e8faa 100644 --- a/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -20,7 +11,7 @@ import SwiftUI typealias RoomMembersListScreenViewModelType = StateStoreViewModel class RoomMembersListScreenViewModel: RoomMembersListScreenViewModelType, RoomMembersListScreenViewModelProtocol { - private let roomProxy: RoomProxyProtocol + private let roomProxy: JoinedRoomProxyProtocol private let userIndicatorController: UserIndicatorControllerProtocol private let analytics: AnalyticsService @@ -33,7 +24,7 @@ class RoomMembersListScreenViewModel: RoomMembersListScreenViewModelType, RoomMe } init(initialMode: RoomMembersListScreenMode = .members, - roomProxy: RoomProxyProtocol, + roomProxy: JoinedRoomProxyProtocol, mediaProvider: MediaProviderProtocol, userIndicatorController: UserIndicatorControllerProtocol, analytics: AnalyticsService) { @@ -43,7 +34,7 @@ class RoomMembersListScreenViewModel: RoomMembersListScreenViewModelType, RoomMe super.init(initialViewState: .init(joinedMembersCount: roomProxy.joinedMembersCount, bindings: .init(mode: initialMode)), - imageProvider: mediaProvider) + mediaProvider: mediaProvider) setupMembers() } diff --git a/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenViewModelProtocol.swift b/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenViewModelProtocol.swift index 76107e37e4..62ec3da1cf 100644 --- a/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListManageMemberSheet.swift b/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListManageMemberSheet.swift index f516409f27..ca99f99108 100644 --- a/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListManageMemberSheet.swift +++ b/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListManageMemberSheet.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -29,7 +20,7 @@ struct RoomMembersListManageMemberSheet: View { Form { AvatarHeaderView(member: member, avatarSize: .user(on: .memberDetails), - imageProvider: context.imageProvider) { + mediaProvider: context.mediaProvider) { EmptyView() } @@ -81,13 +72,13 @@ struct RoomMembersListManageMemberSheet_Previews: PreviewProvider, TestablePrevi actions: [.kick, .ban], context: viewModel.context) .previewDisplayName("Joined") - .snapshot(delay: 0.2) + .snapshotPreferences(delay: 0.2) RoomMembersListManageMemberSheet(member: .init(withProxy: RoomMemberProxyMock.mockBanned[3]), actions: [], context: viewModel.context) .previewDisplayName("Banned") - .snapshot(delay: 0.2) + .snapshotPreferences(delay: 0.2) } } @@ -108,7 +99,7 @@ struct RoomMembersListManageMemberSheetLive_Previews: PreviewProvider { private extension RoomMembersListScreenViewModel { static var mock: RoomMembersListScreenViewModel { RoomMembersListScreenViewModel(initialMode: .members, - roomProxy: RoomProxyMock(.init(members: .allMembersAsAdmin)), + roomProxy: JoinedRoomProxyMock(.init(members: .allMembersAsAdmin)), mediaProvider: MockMediaProvider(), userIndicatorController: ServiceLocator.shared.userIndicatorController, analytics: ServiceLocator.shared.analytics) diff --git a/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreen.swift b/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreen.swift index ee2ca9c2a9..ade0098d71 100644 --- a/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreen.swift +++ b/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -126,31 +117,31 @@ struct RoomMembersListScreen_Previews: PreviewProvider, TestablePreview { NavigationStack { RoomMembersListScreen(context: viewModel.context) } - .snapshot(delay: 1.0) + .snapshotPreferences(delay: 1.0) .previewDisplayName("Member") NavigationStack { RoomMembersListScreen(context: invitesViewModel.context) } - .snapshot(delay: 1.0) + .snapshotPreferences(delay: 1.0) .previewDisplayName("Invites") NavigationStack { RoomMembersListScreen(context: adminViewModel.context) } - .snapshot(delay: 1.0) + .snapshotPreferences(delay: 1.0) .previewDisplayName("Admin: Members") NavigationStack { RoomMembersListScreen(context: bannedViewModel.context) } - .snapshot(delay: 1.0) + .snapshotPreferences(delay: 1.0) .previewDisplayName("Admin: Banned") NavigationStack { RoomMembersListScreen(context: emptyBannedViewModel.context) } - .snapshot(delay: 1.0) + .snapshotPreferences(delay: 1.0) .previewDisplayName("Admin: Empty Banned") } @@ -179,10 +170,10 @@ struct RoomMembersListScreen_Previews: PreviewProvider, TestablePreview { } return RoomMembersListScreenViewModel(initialMode: initialMode, - roomProxy: RoomProxyMock(.init(name: "Some room", - members: members, - ownUserID: ownUserID, - canUserInvite: false)), + roomProxy: JoinedRoomProxyMock(.init(name: "Some room", + members: members, + ownUserID: ownUserID, + canUserInvite: false)), mediaProvider: MockMediaProvider(), userIndicatorController: ServiceLocator.shared.userIndicatorController, analytics: ServiceLocator.shared.analytics) diff --git a/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreenMemberCell.swift b/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreenMemberCell.swift index 2a6d3dbc1e..f84e177565 100644 --- a/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreenMemberCell.swift +++ b/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreenMemberCell.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -29,7 +20,7 @@ struct RoomMembersListScreenMemberCell: View { name: avatarName, contentID: member.id, avatarSize: .user(on: .roomDetails), - imageProvider: context.imageProvider) + mediaProvider: context.mediaProvider) .accessibilityHidden(true) HStack(alignment: .firstTextBaseline, spacing: 4) { @@ -106,8 +97,8 @@ struct RoomMembersListMemberCell_Previews: PreviewProvider, TestablePreview { .init(with: .init(userID: "@badavatar:matrix.org", avatarURL: .picturesDirectory, membership: .ban)) ] - static let viewModel = RoomMembersListScreenViewModel(roomProxy: RoomProxyMock(.init(name: "Some room", - members: members)), + static let viewModel = RoomMembersListScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Some room", + members: members)), mediaProvider: MockMediaProvider(), userIndicatorController: ServiceLocator.shared.userIndicatorController, analytics: ServiceLocator.shared.analytics) diff --git a/ElementX/Sources/Screens/RoomNotificationSettingsScreen/RoomNotificationSettingsScreenCoordinator.swift b/ElementX/Sources/Screens/RoomNotificationSettingsScreen/RoomNotificationSettingsScreenCoordinator.swift index c0b2330eeb..0558ae79ba 100644 --- a/ElementX/Sources/Screens/RoomNotificationSettingsScreen/RoomNotificationSettingsScreenCoordinator.swift +++ b/ElementX/Sources/Screens/RoomNotificationSettingsScreen/RoomNotificationSettingsScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -20,7 +11,7 @@ import SwiftUI struct RoomNotificationSettingsScreenCoordinatorParameters { weak var navigationStackCoordinator: NavigationStackCoordinator? let notificationSettingsProxy: NotificationSettingsProxyProtocol - let roomProxy: RoomProxyProtocol + let roomProxy: JoinedRoomProxyProtocol let displayAsUserDefinedRoomSettings: Bool } diff --git a/ElementX/Sources/Screens/RoomNotificationSettingsScreen/RoomNotificationSettingsScreenModels.swift b/ElementX/Sources/Screens/RoomNotificationSettingsScreen/RoomNotificationSettingsScreenModels.swift index 2a3b105c0d..e88190ffc9 100644 --- a/ElementX/Sources/Screens/RoomNotificationSettingsScreen/RoomNotificationSettingsScreenModels.swift +++ b/ElementX/Sources/Screens/RoomNotificationSettingsScreen/RoomNotificationSettingsScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/RoomNotificationSettingsScreen/RoomNotificationSettingsScreenViewModel.swift b/ElementX/Sources/Screens/RoomNotificationSettingsScreen/RoomNotificationSettingsScreenViewModel.swift index e3fe9b2ca5..1075a58f42 100644 --- a/ElementX/Sources/Screens/RoomNotificationSettingsScreen/RoomNotificationSettingsScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomNotificationSettingsScreen/RoomNotificationSettingsScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -22,7 +13,7 @@ typealias RoomNotificationSettingsScreenViewModelType = StateStoreViewModel = .init() private let notificationSettingsProxy: NotificationSettingsProxyProtocol - private let roomProxy: RoomProxyProtocol + private let roomProxy: JoinedRoomProxyProtocol // periphery:ignore - cancellable tasks cancel when reassigned @CancellableTask private var fetchNotificationSettingsTask: Task? @@ -31,7 +22,7 @@ class RoomNotificationSettingsScreenViewModel: RoomNotificationSettingsScreenVie actionsSubject.eraseToAnyPublisher() } - init(notificationSettingsProxy: NotificationSettingsProxyProtocol, roomProxy: RoomProxyProtocol, displayAsUserDefinedRoomSettings: Bool) { + init(notificationSettingsProxy: NotificationSettingsProxyProtocol, roomProxy: JoinedRoomProxyProtocol, displayAsUserDefinedRoomSettings: Bool) { let bindings = RoomNotificationSettingsScreenViewStateBindings() self.notificationSettingsProxy = notificationSettingsProxy self.roomProxy = roomProxy @@ -149,6 +140,7 @@ class RoomNotificationSettingsScreenViewModel: RoomNotificationSettingsScreenVie state.bindings.alertInfo = AlertInfo(id: type, title: L10n.commonError, message: L10n.screenRoomNotificationSettingsErrorLoadingSettings) + case .setModeFailed: state.bindings.alertInfo = AlertInfo(id: type, title: L10n.commonError, diff --git a/ElementX/Sources/Screens/RoomNotificationSettingsScreen/RoomNotificationSettingsScreenViewModelProtocol.swift b/ElementX/Sources/Screens/RoomNotificationSettingsScreen/RoomNotificationSettingsScreenViewModelProtocol.swift index f037916183..48f9cc5cd4 100644 --- a/ElementX/Sources/Screens/RoomNotificationSettingsScreen/RoomNotificationSettingsScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/RoomNotificationSettingsScreen/RoomNotificationSettingsScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/RoomNotificationSettingsScreen/View/RoomNotificationSettingsCustomSectionView.swift b/ElementX/Sources/Screens/RoomNotificationSettingsScreen/View/RoomNotificationSettingsCustomSectionView.swift index eb70d56af1..df3b9d5731 100644 --- a/ElementX/Sources/Screens/RoomNotificationSettingsScreen/View/RoomNotificationSettingsCustomSectionView.swift +++ b/ElementX/Sources/Screens/RoomNotificationSettingsScreen/View/RoomNotificationSettingsCustomSectionView.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -42,7 +33,7 @@ struct RoomNotificationSettingsCustomSectionView_Previews: PreviewProvider, Test static let viewModel = { let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init(defaultRoomMode: .allMessages, roomMode: .mentionsAndKeywordsOnly)) - let roomProxy = RoomProxyMock(.init(name: "Room", isEncrypted: true)) + let roomProxy = JoinedRoomProxyMock(.init(name: "Room", isEncrypted: true)) return RoomNotificationSettingsScreenViewModel(notificationSettingsProxy: notificationSettingsProxy, roomProxy: roomProxy, @@ -52,7 +43,7 @@ struct RoomNotificationSettingsCustomSectionView_Previews: PreviewProvider, Test static let viewModelUnencrypted = { let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init(defaultRoomMode: .allMessages, roomMode: .mentionsAndKeywordsOnly)) - let roomProxy = RoomProxyMock(.init(name: "Room", isEncrypted: false)) + let roomProxy = JoinedRoomProxyMock(.init(name: "Room", isEncrypted: false)) return RoomNotificationSettingsScreenViewModel(notificationSettingsProxy: notificationSettingsProxy, roomProxy: roomProxy, diff --git a/ElementX/Sources/Screens/RoomNotificationSettingsScreen/View/RoomNotificationSettingsScreen.swift b/ElementX/Sources/Screens/RoomNotificationSettingsScreen/View/RoomNotificationSettingsScreen.swift index e9c7bdbf64..7c1ae23f76 100644 --- a/ElementX/Sources/Screens/RoomNotificationSettingsScreen/View/RoomNotificationSettingsScreen.swift +++ b/ElementX/Sources/Screens/RoomNotificationSettingsScreen/View/RoomNotificationSettingsScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -83,7 +74,7 @@ struct RoomNotificationSettingsScreen_Previews: PreviewProvider, TestablePreview static let viewModel = { let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init(defaultRoomMode: .mentionsAndKeywordsOnly, roomMode: .mentionsAndKeywordsOnly)) - let roomProxy = RoomProxyMock(.init(name: "Room", isEncrypted: true)) + let roomProxy = JoinedRoomProxyMock(.init(name: "Room", isEncrypted: true)) return RoomNotificationSettingsScreenViewModel(notificationSettingsProxy: notificationSettingsProxy, roomProxy: roomProxy, @@ -93,7 +84,7 @@ struct RoomNotificationSettingsScreen_Previews: PreviewProvider, TestablePreview static let viewModelCustom = { let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init(defaultRoomMode: .allMessages, roomMode: .mentionsAndKeywordsOnly)) - let roomProxy = RoomProxyMock(.init(name: "Room", isEncrypted: true)) + let roomProxy = JoinedRoomProxyMock(.init(name: "Room", isEncrypted: true)) return RoomNotificationSettingsScreenViewModel(notificationSettingsProxy: notificationSettingsProxy, roomProxy: roomProxy, diff --git a/ElementX/Sources/Screens/RoomNotificationSettingsScreen/View/RoomNotificationSettingsUserDefinedScreen.swift b/ElementX/Sources/Screens/RoomNotificationSettingsScreen/View/RoomNotificationSettingsUserDefinedScreen.swift index 932273f916..09c242ffdb 100644 --- a/ElementX/Sources/Screens/RoomNotificationSettingsScreen/View/RoomNotificationSettingsUserDefinedScreen.swift +++ b/ElementX/Sources/Screens/RoomNotificationSettingsScreen/View/RoomNotificationSettingsUserDefinedScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -52,7 +43,7 @@ struct RoomNotificationSettingsUserDefinedScreen_Previews: PreviewProvider, Test static let viewModel = { let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init(defaultRoomMode: .mentionsAndKeywordsOnly, roomMode: .mentionsAndKeywordsOnly)) - let roomProxy = RoomProxyMock(.init(name: "Room", isEncrypted: true)) + let roomProxy = JoinedRoomProxyMock(.init(name: "Room", isEncrypted: true)) return RoomNotificationSettingsScreenViewModel(notificationSettingsProxy: notificationSettingsProxy, roomProxy: roomProxy, @@ -62,7 +53,7 @@ struct RoomNotificationSettingsUserDefinedScreen_Previews: PreviewProvider, Test static let viewModelUnencrypted = { let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init(defaultRoomMode: .mentionsAndKeywordsOnly, roomMode: .mentionsAndKeywordsOnly)) - let roomProxy = RoomProxyMock(.init(name: "Room", isEncrypted: false)) + let roomProxy = JoinedRoomProxyMock(.init(name: "Room", isEncrypted: false)) return RoomNotificationSettingsScreenViewModel(notificationSettingsProxy: notificationSettingsProxy, roomProxy: roomProxy, diff --git a/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenCoordinator.swift b/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenCoordinator.swift index 89b9c71b75..3b9d16cf19 100644 --- a/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenCoordinator.swift +++ b/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenModels.swift b/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenModels.swift index 4b12e5b967..6eb3e3da7b 100644 --- a/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenModels.swift +++ b/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenViewModel.swift b/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenViewModel.swift index 1fabb99391..14790737fe 100644 --- a/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Algorithms diff --git a/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenViewModelProtocol.swift b/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenViewModelProtocol.swift index 0e76e2f197..679cc70d73 100644 --- a/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/RoomPollsHistoryScreen/View/RoomPollsHistoryScreen.swift b/ElementX/Sources/Screens/RoomPollsHistoryScreen/View/RoomPollsHistoryScreen.swift index 1b8d20313d..9358e02270 100644 --- a/ElementX/Sources/Screens/RoomPollsHistoryScreen/View/RoomPollsHistoryScreen.swift +++ b/ElementX/Sources/Screens/RoomPollsHistoryScreen/View/RoomPollsHistoryScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -67,7 +58,8 @@ struct RoomPollsHistoryScreen: View { Text(DateFormatter.pollTimestamp.string(from: pollTimelineItem.timestamp)) .font(.compound.bodySM) .foregroundColor(.compound.textSecondary) - PollView(poll: pollTimelineItem.item.poll, editable: pollTimelineItem.item.isEditable) { action in + PollView(poll: pollTimelineItem.item.poll, + state: .full(isEditable: pollTimelineItem.item.isEditable)) { action in switch action { case .selectOption(let optionID): guard let pollStartID = pollTimelineItem.item.id.eventID else { return } @@ -124,7 +116,7 @@ struct RoomPollsHistoryScreen_Previews: PreviewProvider, TestablePreview { static let viewModelEmpty: RoomPollsHistoryScreenViewModel = { let roomTimelineController = MockRoomTimelineController() roomTimelineController.timelineItems = [] - let roomProxyMockConfiguration = RoomProxyMockConfiguration(name: "Polls") + let roomProxyMockConfiguration = JoinedRoomProxyMockConfiguration(name: "Polls") let viewModel = RoomPollsHistoryScreenViewModel(pollInteractionHandler: PollInteractionHandlerMock(), roomTimelineController: roomTimelineController, userIndicatorController: UserIndicatorControllerMock()) @@ -146,7 +138,7 @@ struct RoomPollsHistoryScreen_Previews: PreviewProvider, TestablePreview { roomTimelineController.timelineItemsTimestamp[item.id] = date } - let roomProxyMockConfiguration = RoomProxyMockConfiguration(name: "Polls", timelineStartReached: true) + let roomProxyMockConfiguration = JoinedRoomProxyMockConfiguration(name: "Polls", timelineStartReached: true) let viewModel = RoomPollsHistoryScreenViewModel(pollInteractionHandler: PollInteractionHandlerMock(), roomTimelineController: roomTimelineController, userIndicatorController: UserIndicatorControllerMock()) @@ -159,12 +151,12 @@ struct RoomPollsHistoryScreen_Previews: PreviewProvider, TestablePreview { RoomPollsHistoryScreen(context: viewModelEmpty.context) } .previewDisplayName("No polls") - .snapshot(delay: 1.0) + .snapshotPreferences(delay: 1.0) NavigationStack { RoomPollsHistoryScreen(context: viewModel.context) } .previewDisplayName("polls") - .snapshot(delay: 1.0) + .snapshotPreferences(delay: 1.0) } } diff --git a/ElementX/Sources/Screens/RoomRolesAndPermissionsScreen/RoomRolesAndPermissionsScreenCoordinator.swift b/ElementX/Sources/Screens/RoomRolesAndPermissionsScreen/RoomRolesAndPermissionsScreenCoordinator.swift index c805b6df47..e63186f800 100644 --- a/ElementX/Sources/Screens/RoomRolesAndPermissionsScreen/RoomRolesAndPermissionsScreenCoordinator.swift +++ b/ElementX/Sources/Screens/RoomRolesAndPermissionsScreen/RoomRolesAndPermissionsScreenCoordinator.swift @@ -1,24 +1,15 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine import SwiftUI struct RoomRolesAndPermissionsScreenCoordinatorParameters { - let roomProxy: RoomProxyProtocol + let roomProxy: JoinedRoomProxyProtocol let userIndicatorController: UserIndicatorControllerProtocol let analytics: AnalyticsService } diff --git a/ElementX/Sources/Screens/RoomRolesAndPermissionsScreen/RoomRolesAndPermissionsScreenModels.swift b/ElementX/Sources/Screens/RoomRolesAndPermissionsScreen/RoomRolesAndPermissionsScreenModels.swift index 5adc657d6a..88f9ec1fe7 100644 --- a/ElementX/Sources/Screens/RoomRolesAndPermissionsScreen/RoomRolesAndPermissionsScreenModels.swift +++ b/ElementX/Sources/Screens/RoomRolesAndPermissionsScreen/RoomRolesAndPermissionsScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/RoomRolesAndPermissionsScreen/RoomRolesAndPermissionsScreenViewModel.swift b/ElementX/Sources/Screens/RoomRolesAndPermissionsScreen/RoomRolesAndPermissionsScreenViewModel.swift index 2bd720f285..692a32698b 100644 --- a/ElementX/Sources/Screens/RoomRolesAndPermissionsScreen/RoomRolesAndPermissionsScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomRolesAndPermissionsScreen/RoomRolesAndPermissionsScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -20,7 +11,7 @@ import SwiftUI typealias RoomRolesAndPermissionsScreenViewModelType = StateStoreViewModel class RoomRolesAndPermissionsScreenViewModel: RoomRolesAndPermissionsScreenViewModelType, RoomRolesAndPermissionsScreenViewModelProtocol { - private let roomProxy: RoomProxyProtocol + private let roomProxy: JoinedRoomProxyProtocol private let userIndicatorController: UserIndicatorControllerProtocol private let analytics: AnalyticsService @@ -29,7 +20,7 @@ class RoomRolesAndPermissionsScreenViewModel: RoomRolesAndPermissionsScreenViewM actionsSubject.eraseToAnyPublisher() } - init(initialPermissions: RoomPermissions? = nil, roomProxy: RoomProxyProtocol, userIndicatorController: UserIndicatorControllerProtocol, analytics: AnalyticsService) { + init(initialPermissions: RoomPermissions? = nil, roomProxy: JoinedRoomProxyProtocol, userIndicatorController: UserIndicatorControllerProtocol, analytics: AnalyticsService) { self.roomProxy = roomProxy self.userIndicatorController = userIndicatorController self.analytics = analytics diff --git a/ElementX/Sources/Screens/RoomRolesAndPermissionsScreen/RoomRolesAndPermissionsScreenViewModelProtocol.swift b/ElementX/Sources/Screens/RoomRolesAndPermissionsScreen/RoomRolesAndPermissionsScreenViewModelProtocol.swift index 02a60e2f56..dccc707926 100644 --- a/ElementX/Sources/Screens/RoomRolesAndPermissionsScreen/RoomRolesAndPermissionsScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/RoomRolesAndPermissionsScreen/RoomRolesAndPermissionsScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/RoomRolesAndPermissionsScreen/View/RoomRolesAndPermissionsScreen.swift b/ElementX/Sources/Screens/RoomRolesAndPermissionsScreen/View/RoomRolesAndPermissionsScreen.swift index cb3aef8276..2fbe5faf1b 100644 --- a/ElementX/Sources/Screens/RoomRolesAndPermissionsScreen/View/RoomRolesAndPermissionsScreen.swift +++ b/ElementX/Sources/Screens/RoomRolesAndPermissionsScreen/View/RoomRolesAndPermissionsScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -127,7 +118,7 @@ struct RoomRolesAndPermissionsScreen: View { struct RoomRolesAndPermissionsScreen_Previews: PreviewProvider, TestablePreview { static let viewModel = RoomRolesAndPermissionsScreenViewModel(initialPermissions: RoomPermissions(powerLevels: .mock), - roomProxy: RoomProxyMock(.init(members: .allMembersAsAdmin)), + roomProxy: JoinedRoomProxyMock(.init(members: .allMembersAsAdmin)), userIndicatorController: UserIndicatorControllerMock(), analytics: ServiceLocator.shared.analytics) static var previews: some View { diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/CompletionSuggestionService.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/CompletionSuggestionService.swift index 7ffae706c7..de54046aa0 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/CompletionSuggestionService.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/CompletionSuggestionService.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -22,13 +13,13 @@ private enum SuggestionTriggerPattern: Character { } final class CompletionSuggestionService: CompletionSuggestionServiceProtocol { - private let roomProxy: RoomProxyProtocol + private let roomProxy: JoinedRoomProxyProtocol private var canMentionAllUsers = false private(set) var suggestionsPublisher: AnyPublisher<[SuggestionItem], Never> = Empty().eraseToAnyPublisher() private let suggestionTriggerSubject = CurrentValueSubject(nil) - init(roomProxy: RoomProxyProtocol) { + init(roomProxy: JoinedRoomProxyProtocol) { self.roomProxy = roomProxy suggestionsPublisher = suggestionTriggerSubject diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/CompletionSuggestionServiceProtocol.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/CompletionSuggestionServiceProtocol.swift index ceb121d7d2..4cfa2da2ef 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/CompletionSuggestionServiceProtocol.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/CompletionSuggestionServiceProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarModels.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarModels.swift index 4188d05cc4..9f3f169bfb 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarModels.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -31,13 +22,13 @@ enum ComposerToolbarVoiceMessageAction { } enum ComposerToolbarViewModelAction { - case sendMessage(plain: String, html: String?, mode: RoomScreenComposerMode, intentionalMentions: IntentionalMentions) + case sendMessage(plain: String, html: String?, mode: ComposerMode, intentionalMentions: IntentionalMentions) case editLastMessage case attach(ComposerAttachmentType) case handlePasteOrDrop(provider: NSItemProvider) - case composerModeChanged(mode: RoomScreenComposerMode) + case composerModeChanged(mode: ComposerMode) case composerFocusedChanged(isFocused: Bool) case voiceMessage(ComposerToolbarVoiceMessageAction) @@ -72,7 +63,7 @@ enum ComposerAttachmentType { } struct ComposerToolbarViewState: BindableState { - var composerMode: RoomScreenComposerMode = .default + var composerMode: ComposerMode = .default var composerEmpty = true var suggestions: [SuggestionItem] = [] var audioPlayerState: AudioPlayerState @@ -133,6 +124,8 @@ struct ComposerToolbarViewStateBindings { var composerExpanded = false var formatItems: [FormatItem] = .init() var alertInfo: AlertInfo? + + var presendCallback: (() -> Void)? } /// An item in the toolbar @@ -288,3 +281,61 @@ extension FormatType { } } } + +enum ComposerMode: Equatable { + case `default` + case reply(itemID: TimelineItemIdentifier, replyDetails: TimelineItemReplyDetails, isThread: Bool) + case edit(originalItemId: TimelineItemIdentifier) + case recordVoiceMessage(state: AudioRecorderState) + case previewVoiceMessage(state: AudioPlayerState, waveform: WaveformSource, isUploading: Bool) + + var isEdit: Bool { + switch self { + case .edit: + return true + default: + return false + } + } + + var isTextEditingEnabled: Bool { + switch self { + case .default, .reply, .edit: + return true + case .recordVoiceMessage, .previewVoiceMessage: + return false + } + } + + var isLoadingReply: Bool { + switch self { + case .reply(_, let replyDetails, _): + switch replyDetails { + case .loading: + return true + default: + return false + } + default: + return false + } + } + + var replyEventID: String? { + switch self { + case .reply(let itemID, _, _): + return itemID.eventID + default: + return nil + } + } + + var isComposingNewMessage: Bool { + switch self { + case .default, .reply: + return true + default: + return false + } + } +} diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModel.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModel.swift index c39e48db44..f9bad3c7de 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModel.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -64,10 +55,12 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool mentionBuilder = MentionBuilder() attributedStringBuilder = AttributedStringBuilder(cacheKey: "Composer", mentionBuilder: mentionBuilder) - super.init(initialViewState: ComposerToolbarViewState(audioPlayerState: .init(id: .recorderPreview, duration: 0), + super.init(initialViewState: ComposerToolbarViewState(audioPlayerState: .init(id: .recorderPreview, + title: L10n.commonVoiceMessage, + duration: 0), audioRecorderState: .init(), bindings: .init()), - imageProvider: mediaProvider) + mediaProvider: mediaProvider) context.$viewState .map(\.composerMode) @@ -200,8 +193,8 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool } } - func process(roomAction: RoomScreenComposerAction) { - switch roomAction { + func process(timelineAction: TimelineComposerAction) { + switch timelineAction { case .setMode(mode: let mode): if state.composerMode.isComposingNewMessage, mode.isEdit { handleSaveDraft(isVolatile: true) @@ -223,19 +216,23 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool set(mode: .default) set(text: "") } - case .saveDraft: - handleSaveDraft(isVolatile: false) - case .loadDraft: - Task { - guard case let .success(draft) = await draftService.loadDraft(), - let draft else { - return - } - handleLoadDraft(draft) + } + } + + func loadDraft() { + Task { + guard case let .success(draft) = await draftService.loadDraft(), + let draft else { + return } + handleLoadDraft(draft) } } + func saveDraft() { + handleSaveDraft(isVolatile: false) + } + var keyCommands: [WysiwygKeyCommand] { [ .enter { [weak self] in @@ -480,7 +477,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool } } - private func set(mode: RoomScreenComposerMode) { + private func set(mode: ComposerMode) { if state.composerMode.isLoadingReply, state.composerMode.replyEventID != mode.replyEventID { replyLoadingTask?.cancel() } diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModelProtocol.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModelProtocol.swift index 2cbba8d4ef..88db5d5cba 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModelProtocol.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModelProtocol.swift @@ -1,24 +1,20 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine +import WysiwygComposer // periphery: ignore - markdown protocol protocol ComposerToolbarViewModelProtocol { var actions: AnyPublisher { get } var context: ComposerToolbarViewModelType.Context { get } - func process(roomAction: RoomScreenComposerAction) + var keyCommands: [WysiwygKeyCommand] { get } + + func process(timelineAction: TimelineComposerAction) + func loadDraft() + func saveDraft() } diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/CompletionSuggestionView.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/CompletionSuggestionView.swift index dcc98b7e6d..fcb0536b98 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/CompletionSuggestionView.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/CompletionSuggestionView.swift @@ -1,23 +1,14 @@ // -// Copyright 2021 New Vector Ltd +// Copyright 2021-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI struct CompletionSuggestionView: View { - let imageProvider: ImageProviderProtocol? + let mediaProvider: MediaProviderProtocol? let items: [SuggestionItem] var showBackgroundShadow = true let onTap: (SuggestionItem) -> Void @@ -41,7 +32,7 @@ struct CompletionSuggestionView: View { EmptyView() } else { ZStack { - MentionSuggestionItemView(imageProvider: nil, item: .init(id: "", displayName: nil, avatarURL: nil, range: .init())) + MentionSuggestionItemView(mediaProvider: nil, item: .init(id: "", displayName: nil, avatarURL: nil, range: .init())) .readFrame($prototypeListItemFrame) .hidden() if showBackgroundShadow { @@ -63,7 +54,7 @@ struct CompletionSuggestionView: View { } label: { switch item { case .user(let mention), .allUsers(let mention): - MentionSuggestionItemView(imageProvider: imageProvider, item: mention) + MentionSuggestionItemView(mediaProvider: mediaProvider, item: mention) } } .modifier(ListItemPaddingModifier(isFirst: items.first?.id == item.id)) @@ -125,12 +116,12 @@ struct CompletionSuggestion_Previews: PreviewProvider, TestablePreview { static var previews: some View { // Putting them is VStack allows the preview to work properly in tests VStack(spacing: 8) { - CompletionSuggestionView(imageProvider: MockMediaProvider(), + CompletionSuggestionView(mediaProvider: MockMediaProvider(), 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 } } VStack(spacing: 8) { - CompletionSuggestionView(imageProvider: MockMediaProvider(), + CompletionSuggestionView(mediaProvider: MockMediaProvider(), items: multipleItems) { _ in } } } diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/ComposerToolbar.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/ComposerToolbar.swift index d6942e73c9..4f20be1a38 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/ComposerToolbar.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/ComposerToolbar.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -57,7 +48,7 @@ struct ComposerToolbar: View { } private var suggestionView: some View { - CompletionSuggestionView(imageProvider: context.imageProvider, + CompletionSuggestionView(mediaProvider: context.mediaProvider, items: context.viewState.suggestions, showBackgroundShadow: !context.composerExpanded) { suggestion in context.send(viewAction: .selectedSuggestion(suggestion)) @@ -137,7 +128,7 @@ struct ComposerToolbar: View { private var sendButton: some View { Button { - context.send(viewAction: .sendMessage) + sendMessage() } label: { CompoundIcon(context.viewState.composerMode.isEdit ? \.check : \.sendSolid) .scaledPadding(6, relativeTo: .title) @@ -156,12 +147,13 @@ struct ComposerToolbar: View { private var messageComposer: some View { MessageComposer(plainComposerText: $context.plainComposerText, + presendCallback: $context.presendCallback, composerView: composerView, mode: context.viewState.composerMode, composerFormattingEnabled: context.composerFormattingEnabled, showResizeGrabber: context.composerFormattingEnabled, isExpanded: $context.composerExpanded) { - context.send(viewAction: .sendMessage) + sendMessage() } editAction: { context.send(viewAction: .editLastMessage) } pasteAction: { provider in @@ -205,6 +197,17 @@ struct ComposerToolbar: View { } } + private func sendMessage() { + // Allow the inner TextField do apply any final processing before + // sending e.g. accepting current autocorrection. + // Fixes https://github.com/element-hq/element-x-ios/issues/3216 + context.presendCallback?() + + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + context.send(viewAction: .sendMessage) + } + } + private var placeholder: String { switch context.viewState.composerMode { case .reply(_, _, let isThread): @@ -389,7 +392,11 @@ extension ComposerToolbar { mentionDisplayHelper: ComposerMentionDisplayHelper.mock, analyticsService: ServiceLocator.shared.analytics, composerDraftService: ComposerDraftServiceMock()) - model.state.composerMode = .previewVoiceMessage(state: AudioPlayerState(id: .recorderPreview, duration: 10.0), waveform: .data(waveformData), isUploading: uploading) + model.state.composerMode = .previewVoiceMessage(state: AudioPlayerState(id: .recorderPreview, + title: L10n.commonVoiceMessage, + duration: 10.0), + waveform: .data(waveformData), + isUploading: uploading) return model } return ComposerToolbar(context: composerViewModel.context, diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/FormattingToolbar.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/FormattingToolbar.swift index 67b6c326e4..8ae12382f2 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/FormattingToolbar.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/FormattingToolbar.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MentionSuggestionItemView.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MentionSuggestionItemView.swift index 19a61bcba5..41e29b414d 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MentionSuggestionItemView.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MentionSuggestionItemView.swift @@ -1,23 +1,14 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI struct MentionSuggestionItemView: View { - let imageProvider: ImageProviderProtocol? + let mediaProvider: MediaProviderProtocol? let item: MentionSuggestionItem var body: some View { @@ -26,7 +17,7 @@ struct MentionSuggestionItemView: View { name: item.displayName, contentID: item.id, avatarSize: .user(on: .suggestions), - imageProvider: imageProvider) + mediaProvider: mediaProvider) VStack(alignment: .leading, spacing: 0) { Text(item.displayName ?? item.id) .font(.compound.bodyLG) @@ -47,7 +38,7 @@ struct MentionSuggestionItemView_Previews: PreviewProvider, TestablePreview { static let mockMediaProvider = MockMediaProvider() static var previews: some View { - MentionSuggestionItemView(imageProvider: mockMediaProvider, item: .init(id: "test", displayName: "Test", avatarURL: URL.documentsDirectory, range: .init())) - MentionSuggestionItemView(imageProvider: mockMediaProvider, item: .init(id: "test2", displayName: nil, avatarURL: nil, range: .init())) + MentionSuggestionItemView(mediaProvider: mockMediaProvider, item: .init(id: "test", displayName: "Test", avatarURL: URL.documentsDirectory, range: .init())) + MentionSuggestionItemView(mediaProvider: mockMediaProvider, item: .init(id: "test2", displayName: nil, avatarURL: nil, range: .init())) } } diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift index 5514ac92b2..85e0fd018d 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -23,8 +14,9 @@ typealias PasteHandler = (NSItemProvider) -> Void struct MessageComposer: View { @Binding var plainComposerText: NSAttributedString + @Binding var presendCallback: (() -> Void)? let composerView: WysiwygComposerView - let mode: RoomScreenComposerMode + let mode: ComposerMode let composerFormattingEnabled: Bool let showResizeGrabber: Bool @Binding var isExpanded: Bool @@ -86,7 +78,8 @@ struct MessageComposer: View { } else { MessageComposerTextField(placeholder: L10n.richTextEditorComposerPlaceholder, text: $plainComposerText, - maxHeight: 300, + presendCallback: $presendCallback, + maxHeight: ComposerConstant.maxHeight, keyHandler: { handleKeyPress($0) }, pasteHandler: pasteAction) .tint(.compound.iconAccentTertiary) @@ -208,7 +201,7 @@ private struct MessageComposerHeaderLabelStyle: LabelStyle { } struct MessageComposer_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock + static let viewModel = TimelineViewModel.mock static let replyTypes: [TimelineItemReplyDetails] = [ .loaded(sender: .init(id: "Dave"), @@ -241,7 +234,7 @@ struct MessageComposer_Previews: PreviewProvider, TestablePreview { ] static func messageComposer(_ content: NSAttributedString = .init(string: ""), - mode: RoomScreenComposerMode = .default) -> MessageComposer { + mode: ComposerMode = .default) -> MessageComposer { let viewModel = WysiwygComposerViewModel(minHeight: 22, maxExpandedHeight: 250) viewModel.setMarkdownContent(content.string) @@ -253,6 +246,7 @@ struct MessageComposer_Previews: PreviewProvider, TestablePreview { pasteHandler: nil) return MessageComposer(plainComposerText: .constant(content), + presendCallback: .constant(nil), composerView: composerView, mode: mode, composerFormattingEnabled: false, diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposerTextField.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposerTextField.swift index 1bbf06235c..05469baf14 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposerTextField.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposerTextField.swift @@ -1,23 +1,17 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // + +import Compound import SwiftUI struct MessageComposerTextField: View { let placeholder: String @Binding var text: NSAttributedString + @Binding var presendCallback: (() -> Void)? let maxHeight: CGFloat let keyHandler: GenericKeyHandler @@ -25,6 +19,7 @@ struct MessageComposerTextField: View { var body: some View { UITextViewWrapper(text: $text, + presendCallback: $presendCallback, maxHeight: maxHeight, keyHandler: keyHandler, pasteHandler: pasteHandler) @@ -55,9 +50,10 @@ struct MessageComposerTextField: View { } private struct UITextViewWrapper: UIViewRepresentable { - @Environment(\.roomContext) private var roomContext + @Environment(\.timelineContext) private var timelineContext @Binding var text: NSAttributedString + @Binding var presendCallback: (() -> Void)? let maxHeight: CGFloat @@ -68,8 +64,8 @@ private struct UITextViewWrapper: UIViewRepresentable { func makeUIView(context: UIViewRepresentableContext) -> UITextView { // Need to use TextKit 1 for mentions - let textView = ElementTextView(usingTextLayoutManager: false) - textView.roomContext = roomContext + let textView = ElementTextView(timelineContext: timelineContext, + presendCallback: $presendCallback) textView.delegate = context.coordinator textView.elementDelegate = context.coordinator @@ -102,7 +98,7 @@ private struct UITextViewWrapper: UIViewRepresentable { func updateUIView(_ textView: UITextView, context: UIViewRepresentableContext) { // Prevent the textView from inheriting attributes from mention pills textView.typingAttributes = [.font: font, - .foregroundColor: UIColor(.compound.textPrimary)] + .foregroundColor: UIColor.compound.textPrimary] if textView.attributedText != text { // Remember the selection if only the attributes have changed. @@ -182,12 +178,32 @@ private protocol ElementTextViewDelegate: AnyObject { } private class ElementTextView: UITextView, PillAttachmentViewProviderDelegate { - var roomContext: RoomScreenViewModel.Context? + private(set) var timelineContext: TimelineViewModel.Context? + private var presendCallback: Binding<(() -> Void)?> + private var pillViews = NSHashTable.weakObjects() weak var elementDelegate: ElementTextViewDelegate? - private var pillViews = NSHashTable.weakObjects() - + init(timelineContext: TimelineViewModel.Context?, + presendCallback: Binding<(() -> Void)?>) { + self.timelineContext = timelineContext + self.presendCallback = presendCallback + + super.init(frame: .zero, textContainer: nil) + + // Avoid `Publishing changes from within view update` warnings + DispatchQueue.main.async { + presendCallback.wrappedValue = { [weak self] in + self?.acceptCurrentSuggestion() + } + } + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError() + } + override var keyCommands: [UIKeyCommand]? { [UIKeyCommand(input: "\r", modifierFlags: .shift, action: #selector(shiftEnterKeyPressed)), UIKeyCommand(input: "\r", modifierFlags: [], action: #selector(enterKeyPressed))] @@ -270,6 +286,17 @@ private class ElementTextView: UITextView, PillAttachmentViewProviderDelegate { } pillViews.removeAllObjects() } + + // MARK: - Private + + private func acceptCurrentSuggestion() { + guard isFirstResponder else { + return + } + + inputDelegate?.selectionWillChange(self) + inputDelegate?.selectionDidChange(self) + } } struct MessageComposerTextField_Previews: PreviewProvider, TestablePreview { @@ -286,12 +313,13 @@ struct MessageComposerTextField_Previews: PreviewProvider, TestablePreview { init(text: String) { _text = .init(initialValue: .init(string: text, attributes: [.font: UIFont.preferredFont(forTextStyle: .body), - .foregroundColor: UIColor(.compound.textPrimary)])) + .foregroundColor: UIColor.compound.textPrimary])) } var body: some View { MessageComposerTextField(placeholder: "Placeholder", text: $text, + presendCallback: .constant(nil), maxHeight: 300, keyHandler: { _ in }, pasteHandler: { _ in }) diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/RoomAttachmentPicker.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/RoomAttachmentPicker.swift index 2615be8bc8..0871f4f9db 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/RoomAttachmentPicker.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/RoomAttachmentPicker.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessagePreviewComposer.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessagePreviewComposer.swift index 25673a9a19..f290780761 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessagePreviewComposer.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessagePreviewComposer.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import DSWaveformImage @@ -106,6 +97,7 @@ private extension DateFormatter { struct VoiceMessagePreviewComposer_Previews: PreviewProvider, TestablePreview { static let playerState = AudioPlayerState(id: .recorderPreview, + title: L10n.commonVoiceMessage, duration: 10.0, waveform: EstimatedWaveform.mockWaveform, progress: 0.4) diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessageRecordingButton.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessageRecordingButton.swift index 3715fb1702..8688f0f6cf 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessageRecordingButton.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessageRecordingButton.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessageRecordingComposer.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessageRecordingComposer.swift index d05f9682cb..975ad785a2 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessageRecordingComposer.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessageRecordingComposer.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessageRecordingView.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessageRecordingView.swift index 57ca551ad2..0365d169dc 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessageRecordingView.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessageRecordingView.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift index 62b1b59efb..f1bbc1506d 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift @@ -1,33 +1,26 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine +import Compound import HTMLParser import SwiftUI import WysiwygComposer struct RoomScreenCoordinatorParameters { - let roomProxy: RoomProxyProtocol - var focussedEventID: String? + let roomProxy: JoinedRoomProxyProtocol + var focussedEvent: FocusEvent? let timelineController: RoomTimelineControllerProtocol let mediaProvider: MediaProviderProtocol let mediaPlayerProvider: MediaPlayerProviderProtocol let voiceMessageMediaManager: VoiceMessageMediaManagerProtocol let emojiProvider: EmojiProviderProtocol let completionSuggestionService: CompletionSuggestionServiceProtocol + let ongoingCallRoomIDPublisher: CurrentValuePublisher let appMediator: AppMediatorProtocol let appSettings: AppSettings let composerDraftService: ComposerDraftServiceProtocol @@ -46,11 +39,13 @@ enum RoomScreenCoordinatorAction { case presentMessageForwarding(forwardingItem: MessageForwardingItem) case presentCallScreen case presentPinnedEventsTimeline + case presentResolveSendFailure(failure: TimelineItemSendFailure.VerifiedUser, itemID: TimelineItemIdentifier) } final class RoomScreenCoordinator: CoordinatorProtocol { - private var viewModel: RoomScreenViewModelProtocol - private var composerViewModel: ComposerToolbarViewModel + private var roomViewModel: RoomScreenViewModelProtocol + private var timelineViewModel: TimelineViewModelProtocol + private var composerViewModel: ComposerToolbarViewModelProtocol private var wysiwygViewModel: WysiwygComposerViewModel private var cancellables = Set() @@ -61,31 +56,44 @@ final class RoomScreenCoordinator: CoordinatorProtocol { } init(parameters: RoomScreenCoordinatorParameters) { - let viewModel = RoomScreenViewModel(roomProxy: parameters.roomProxy, - focussedEventID: parameters.focussedEventID, - timelineController: parameters.timelineController, + var selectedPinnedEventID: String? + if let focussedEvent = parameters.focussedEvent { + selectedPinnedEventID = focussedEvent.shouldSetPin ? focussedEvent.eventID : nil + } + + roomViewModel = RoomScreenViewModel(roomProxy: parameters.roomProxy, + initialSelectedPinnedEventID: selectedPinnedEventID, mediaProvider: parameters.mediaProvider, - mediaPlayerProvider: parameters.mediaPlayerProvider, - voiceMessageMediaManager: parameters.voiceMessageMediaManager, - userIndicatorController: ServiceLocator.shared.userIndicatorController, + ongoingCallRoomIDPublisher: parameters.ongoingCallRoomIDPublisher, appMediator: parameters.appMediator, - appSettings: parameters.appSettings, + appSettings: ServiceLocator.shared.settings, analyticsService: ServiceLocator.shared.analytics) - self.viewModel = viewModel + + timelineViewModel = TimelineViewModel(roomProxy: parameters.roomProxy, + focussedEventID: parameters.focussedEvent?.eventID, + timelineController: parameters.timelineController, + mediaProvider: parameters.mediaProvider, + mediaPlayerProvider: parameters.mediaPlayerProvider, + voiceMessageMediaManager: parameters.voiceMessageMediaManager, + userIndicatorController: ServiceLocator.shared.userIndicatorController, + appMediator: parameters.appMediator, + appSettings: parameters.appSettings, + analyticsService: ServiceLocator.shared.analytics) wysiwygViewModel = WysiwygComposerViewModel(minHeight: ComposerConstant.minHeight, maxCompressedHeight: ComposerConstant.maxHeight, maxExpandedHeight: ComposerConstant.maxHeight, parserStyle: .elementX) - composerViewModel = ComposerToolbarViewModel(wysiwygViewModel: wysiwygViewModel, - completionSuggestionService: parameters.completionSuggestionService, - mediaProvider: parameters.mediaProvider, - mentionDisplayHelper: ComposerMentionDisplayHelper(roomContext: viewModel.context), - analyticsService: ServiceLocator.shared.analytics, - composerDraftService: parameters.composerDraftService) + let composerViewModel = ComposerToolbarViewModel(wysiwygViewModel: wysiwygViewModel, + completionSuggestionService: parameters.completionSuggestionService, + mediaProvider: parameters.mediaProvider, + mentionDisplayHelper: ComposerMentionDisplayHelper(timelineContext: timelineViewModel.context), + analyticsService: ServiceLocator.shared.analytics, + composerDraftService: parameters.composerDraftService) + self.composerViewModel = composerViewModel NotificationCenter.default.publisher(for: UIApplication.willResignActiveNotification).sink { _ in - viewModel.saveDraft() + composerViewModel.saveDraft() } .store(in: &cancellables) } @@ -93,13 +101,11 @@ final class RoomScreenCoordinator: CoordinatorProtocol { // MARK: - Public func start() { - viewModel.actions + timelineViewModel.actions .sink { [weak self] action in guard let self else { return } switch action { - case .displayRoomDetails: - actionsSubject.send(.presentRoomDetails) case .displayEmojiPicker(let itemID, let selectedEmojis): actionsSubject.send(.presentEmojiPicker(itemID: itemID, selectedEmojis: selectedEmojis)) case .displayReportContent(let itemID, let senderID): @@ -116,18 +122,20 @@ final class RoomScreenCoordinator: CoordinatorProtocol { actionsSubject.send(.presentPollForm(mode: mode)) case .displayMediaUploadPreviewScreen(let url): actionsSubject.send(.presentMediaUploadPreviewScreen(url)) - case .displayRoomMemberDetails(userID: let userID): + case .tappedOnSenderDetails(userID: let userID): actionsSubject.send(.presentRoomMemberDetails(userID: userID)) case .displayMessageForwarding(let forwardingItem): 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 .composer(let action): - composerViewModel.process(roomAction: action) - case .displayCallScreen: - actionsSubject.send(.presentCallScreen) - case .displayPinnedEventsTimeline: - actionsSubject.send(.presentPinnedEventsTimeline) + composerViewModel.process(timelineAction: action) + case .hasScrolled(direction: let direction): + roomViewModel.timelineHasScrolled(direction: direction) + case .viewInRoomTimeline: + fatalError("The action: \(action) should not be sent to this coordinator") } } .store(in: &cancellables) @@ -136,21 +144,44 @@ final class RoomScreenCoordinator: CoordinatorProtocol { .sink { [weak self] action in guard let self else { return } - viewModel.process(composerAction: action) + timelineViewModel.process(composerAction: action) + } + .store(in: &cancellables) + + roomViewModel.actions + .sink { [weak self] actions in + guard let self else { return } + + switch actions { + case .focusEvent(eventID: let eventID): + focusOnEvent(FocusEvent(eventID: eventID, shouldSetPin: false)) + case .displayPinnedEventsTimeline: + actionsSubject.send(.presentPinnedEventsTimeline) + case .displayRoomDetails: + actionsSubject.send(.presentRoomDetails) + case .displayCall: + actionsSubject.send(.presentCallScreen) + case .removeComposerFocus: + composerViewModel.process(timelineAction: .removeFocus) + } } .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. - viewModel.loadDraft() + composerViewModel.loadDraft() } - func focusOnEvent(eventID: String) { - Task { await viewModel.focusOnEvent(eventID: eventID) } + func focusOnEvent(_ focussedEvent: FocusEvent) { + let eventID = focussedEvent.eventID + if focussedEvent.shouldSetPin { + roomViewModel.setSelectedPinnedEventID(eventID) + } + Task { await timelineViewModel.focusOnEvent(eventID: eventID) } } func stop() { - viewModel.saveDraft() - viewModel.stop() + composerViewModel.saveDraft() + timelineViewModel.stop() } func toPresentable() -> AnyView { @@ -158,10 +189,12 @@ final class RoomScreenCoordinator: CoordinatorProtocol { wysiwygViewModel: wysiwygViewModel, keyCommands: composerViewModel.keyCommands) - return AnyView(RoomScreen(context: viewModel.context, composerToolbar: composerToolbar) - .onDisappear { [weak self] in - self?.viewModel.saveDraft() - }) + return AnyView(RoomScreen(roomViewModel: roomViewModel, + timelineViewModel: timelineViewModel, + composerToolbar: composerToolbar) + .onDisappear { [weak self] in + self?.composerViewModel.saveDraft() + }) } } @@ -175,14 +208,14 @@ enum ComposerConstant { private extension HTMLParserStyle { static let elementX = HTMLParserStyle(textColor: UIColor.label, linkColor: UIColor.link, - codeBlockStyle: BlockStyle(backgroundColor: UIColor(.compound._bgCodeBlock), - borderColor: UIColor(.compound.borderInteractiveSecondary), + codeBlockStyle: BlockStyle(backgroundColor: UIColor.compound._bgCodeBlock, + borderColor: UIColor.compound.borderInteractiveSecondary, borderWidth: 1.0, cornerRadius: 2.0, padding: BlockStyle.Padding(horizontal: 10, vertical: 12), type: .background), - quoteBlockStyle: BlockStyle(backgroundColor: UIColor(.compound.iconTertiary), - borderColor: UIColor(.compound.borderInteractiveSecondary), + quoteBlockStyle: BlockStyle(backgroundColor: UIColor.compound.iconTertiary, + borderColor: UIColor.compound.borderInteractiveSecondary, borderWidth: 0.0, cornerRadius: 0.0, padding: BlockStyle.Padding(horizontal: 25, vertical: 12), diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenInteractionHandler.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenInteractionHandler.swift deleted file mode 100644 index 452407077c..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenInteractionHandler.swift +++ /dev/null @@ -1,572 +0,0 @@ -// -// Copyright 2023 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Combine -import UIKit - -enum RoomScreenInteractionHandlerAction { - case composer(action: RoomScreenComposerAction) - - case displayEmojiPicker(itemID: TimelineItemIdentifier, selectedEmojis: Set) - case displayReportContent(itemID: TimelineItemIdentifier, senderID: String) - case displayMessageForwarding(itemID: TimelineItemIdentifier) - case displayMediaUploadPreviewScreen(url: URL) - case displayPollForm(mode: PollFormMode) - case displayRoomMemberDetails(userID: String) - - case showActionMenu(TimelineItemActionMenuInfo) - case showDebugInfo(TimelineItemDebugInfo) - - case displayAudioRecorderPermissionError - case displayErrorToast(String) -} - -@MainActor -class RoomScreenInteractionHandler { - private let roomProxy: RoomProxyProtocol - private let timelineController: RoomTimelineControllerProtocol - private let mediaProvider: MediaProviderProtocol - private let mediaPlayerProvider: MediaPlayerProviderProtocol - private let voiceMessageRecorder: VoiceMessageRecorderProtocol - private let voiceMessageMediaManager: VoiceMessageMediaManagerProtocol - private let userIndicatorController: UserIndicatorControllerProtocol - private let appMediator: AppMediatorProtocol - private let appSettings: AppSettings - private let analyticsService: AnalyticsService - private let pollInteractionHandler: PollInteractionHandlerProtocol - - private let actionsSubject: PassthroughSubject = .init() - var actions: AnyPublisher { - actionsSubject.eraseToAnyPublisher() - } - - private var voiceMessageRecorderObserver: AnyCancellable? { - didSet { - appMediator.setIdleTimerDisabled(voiceMessageRecorderObserver != nil) - } - } - - private var resumeVoiceMessagePlaybackAfterScrubbing = false - - init(roomProxy: RoomProxyProtocol, - timelineController: RoomTimelineControllerProtocol, - mediaProvider: MediaProviderProtocol, - mediaPlayerProvider: MediaPlayerProviderProtocol, - voiceMessageMediaManager: VoiceMessageMediaManagerProtocol, - voiceMessageRecorder: VoiceMessageRecorderProtocol, - userIndicatorController: UserIndicatorControllerProtocol, - appMediator: AppMediatorProtocol, - appSettings: AppSettings, - analyticsService: AnalyticsService) { - self.roomProxy = roomProxy - self.timelineController = timelineController - self.mediaProvider = mediaProvider - self.mediaPlayerProvider = mediaPlayerProvider - self.voiceMessageMediaManager = voiceMessageMediaManager - self.voiceMessageRecorder = voiceMessageRecorder - self.userIndicatorController = userIndicatorController - self.appMediator = appMediator - self.appSettings = appSettings - self.analyticsService = analyticsService - pollInteractionHandler = PollInteractionHandler(analyticsService: analyticsService, roomProxy: roomProxy) - } - - // MARK: Timeline Item Action Menu - - func displayTimelineItemActionMenu(for itemID: TimelineItemIdentifier) { - Task { - guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID), - let eventTimelineItem = timelineItem as? EventBasedTimelineItemProtocol else { - // Don't show a menu for non-event based items. - return - } - - actionsSubject.send(.composer(action: .removeFocus)) - actionsSubject.send(.showActionMenu(.init(item: eventTimelineItem))) - } - } - - func handleTimelineItemMenuAction(_ action: TimelineItemMenuAction, itemID: TimelineItemIdentifier) { - guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID), - let eventTimelineItem = timelineItem as? EventBasedTimelineItemProtocol else { - return - } - - switch action { - case .copy: - guard let messageTimelineItem = timelineItem as? EventBasedMessageTimelineItemProtocol else { - return - } - - UIPasteboard.general.string = messageTimelineItem.body - case .edit: - switch timelineItem { - case let messageTimelineItem as EventBasedMessageTimelineItemProtocol: - processEditMessageEvent(messageTimelineItem) - case let pollTimelineItem as PollRoomTimelineItem: - guard let eventID = pollTimelineItem.id.eventID else { - MXLog.error("Cannot edit poll with id: \(timelineItem.id)") - return - } - actionsSubject.send(.displayPollForm(mode: .edit(eventID: eventID, poll: pollTimelineItem.poll))) - default: - MXLog.error("Cannot edit item with id: \(timelineItem.id)") - } - case .copyPermalink: - guard let eventID = eventTimelineItem.id.eventID else { - actionsSubject.send(.displayErrorToast(L10n.errorFailedCreatingThePermalink)) - return - } - - Task { - guard case let .success(permalinkURL) = await roomProxy.matrixToEventPermalink(eventID) else { - actionsSubject.send(.displayErrorToast(L10n.errorFailedCreatingThePermalink)) - return - } - - UIPasteboard.general.url = permalinkURL - } - case .redact: - Task { - await timelineController.redact(itemID) - } - case .reply: - 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) - - actionsSubject.send(.composer(action: .setMode(mode: .reply(itemID: eventTimelineItem.id, replyDetails: replyDetails, isThread: replyInfo.isThread)))) - case .forward(let itemID): - actionsSubject.send(.displayMessageForwarding(itemID: itemID)) - case .viewSource: - let debugInfo = timelineController.debugInfo(for: eventTimelineItem.id) - MXLog.info("Showing debug info for \(eventTimelineItem.id)") - actionsSubject.send(.showDebugInfo(debugInfo)) - case .retryDecryption(let sessionID): - Task { - await timelineController.retryDecryption(for: sessionID) - } - case .report: - actionsSubject.send(.displayReportContent(itemID: itemID, senderID: eventTimelineItem.sender.id)) - case .react: - displayEmojiPicker(for: itemID) - case .toggleReaction(let key): - guard let eventID = itemID.eventID else { return } - Task { await roomProxy.timeline.toggleReaction(key, to: eventID) } - case .endPoll(let pollStartID): - endPoll(pollStartID: pollStartID) - case .pin: - guard let eventID = itemID.eventID else { return } - Task { await timelineController.pin(eventID: eventID) } - case .unpin: - guard let eventID = itemID.eventID else { return } - Task { await timelineController.unpin(eventID: eventID) } - } - - if action.switchToDefaultComposer { - actionsSubject.send(.composer(action: .setMode(mode: .default))) - } - } - - private func processEditMessageEvent(_ messageTimelineItem: EventBasedMessageTimelineItemProtocol) { - let text: String - var htmlText: String? - switch messageTimelineItem.contentType { - case .text(let content): - text = content.body - htmlText = content.formattedBodyHTMLString - case .emote(let content): - text = "/me " + content.body - 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(originalItemId: messageTimelineItem.id)))) - actionsSubject.send(.composer(action: .setText(plainText: text, htmlText: htmlText))) - } - - // MARK: Polls - - func sendPollResponse(pollStartID: String, optionID: String) { - Task { - let sendPollResponseResult = await pollInteractionHandler.sendPollResponse(pollStartID: pollStartID, optionID: optionID) - - switch sendPollResponseResult { - case .success: - break - case .failure: - actionsSubject.send(.displayErrorToast(L10n.errorUnknown)) - } - } - } - - func endPoll(pollStartID: String) { - Task { - let endPollResult = await pollInteractionHandler.endPoll(pollStartID: pollStartID) - - switch endPollResult { - case .success: - break - case .failure: - actionsSubject.send(.displayErrorToast(L10n.errorUnknown)) - } - } - } - - // 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)") - } - } - } - } - - // MARK: Voice messages - - private func handleVoiceMessageRecorderAction(_ action: VoiceMessageRecorderAction) { - MXLog.debug("handling voice recorder action: \(action) - (audio)") - switch action { - case .didStartRecording(let audioRecorder): - let audioRecordState = AudioRecorderState() - audioRecordState.attachAudioRecorder(audioRecorder) - actionsSubject.send(.composer(action: .setMode(mode: .recordVoiceMessage(state: audioRecordState)))) - case .didStopRecording(let previewAudioPlayerState, let url): - actionsSubject.send(.composer(action: .setMode(mode: .previewVoiceMessage(state: previewAudioPlayerState, waveform: .url(url), isUploading: false)))) - voiceMessageRecorderObserver = nil - case .didFailWithError(let error): - switch error { - case .audioRecorderError(.recordPermissionNotGranted): - MXLog.info("permission to record audio has not been granted.") - actionsSubject.send(.displayAudioRecorderPermissionError) - default: - MXLog.error("failed to start voice message recording. \(error)") - actionsSubject.send(.composer(action: .setMode(mode: .default))) - } - } - } - - func startRecordingVoiceMessage() async { - voiceMessageRecorderObserver = voiceMessageRecorder.actions - .receive(on: DispatchQueue.main) - .sink { [weak self] action in - self?.handleVoiceMessageRecorderAction(action) - } - - await voiceMessageRecorder.startRecording() - } - - func stopRecordingVoiceMessage() async { - await voiceMessageRecorder.stopRecording() - } - - func cancelRecordingVoiceMessage() async { - await voiceMessageRecorder.cancelRecording() - voiceMessageRecorderObserver = nil - actionsSubject.send(.composer(action: .setMode(mode: .default))) - } - - func deleteCurrentVoiceMessage() async { - if voiceMessageRecorder.isRecording { - await voiceMessageRecorder.cancelRecording() - } else { - await voiceMessageRecorder.deleteRecording() - } - - voiceMessageRecorderObserver = nil - actionsSubject.send(.composer(action: .setMode(mode: .default))) - } - - func sendCurrentVoiceMessage() async { - guard let audioPlayerState = voiceMessageRecorder.previewAudioPlayerState, let recordingURL = voiceMessageRecorder.recordingURL else { - actionsSubject.send(.displayErrorToast(L10n.errorFailedUploadingVoiceMessage)) - return - } - - analyticsService.trackComposer(inThread: false, - isEditing: false, - isReply: false, - messageType: .VoiceMessage, - startsThread: nil) - - actionsSubject.send(.composer(action: .setMode(mode: .previewVoiceMessage(state: audioPlayerState, waveform: .url(recordingURL), isUploading: true)))) - await voiceMessageRecorder.stopPlayback() - switch await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy, audioConverter: AudioConverter()) { - case .success: - await deleteCurrentVoiceMessage() - case .failure(let error): - MXLog.error("failed to send the voice message. \(error)") - actionsSubject.send(.composer(action: .setMode(mode: .previewVoiceMessage(state: audioPlayerState, waveform: .url(recordingURL), isUploading: false)))) - actionsSubject.send(.displayErrorToast(L10n.errorFailedUploadingVoiceMessage)) - } - } - - func startPlayingRecordedVoiceMessage() async { - await mediaPlayerProvider.detachAllStates(except: voiceMessageRecorder.previewAudioPlayerState) - if case .failure(let error) = await voiceMessageRecorder.startPlayback() { - MXLog.error("failed to play recorded voice message. \(error)") - } - } - - func pausePlayingRecordedVoiceMessage() { - voiceMessageRecorder.pausePlayback() - } - - func seekRecordedVoiceMessage(to progress: Double) async { - await mediaPlayerProvider.detachAllStates(except: voiceMessageRecorder.previewAudioPlayerState) - await voiceMessageRecorder.seekPlayback(to: progress) - } - - func scrubVoiceMessagePlayback(scrubbing: Bool) async { - guard let audioPlayerState = voiceMessageRecorder.previewAudioPlayerState else { - return - } - if scrubbing { - if audioPlayerState.playbackState == .playing { - resumeVoiceMessagePlaybackAfterScrubbing = true - pausePlayingRecordedVoiceMessage() - } - } else { - if resumeVoiceMessagePlaybackAfterScrubbing { - resumeVoiceMessagePlaybackAfterScrubbing = false - await startPlayingRecordedVoiceMessage() - } - } - } - - // MARK: Audio Playback - - // swiftlint:disable:next cyclomatic_complexity - func playPauseAudio(for itemID: TimelineItemIdentifier) async { - MXLog.info("Toggle play/pause audio for itemID \(itemID)") - guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID) else { - fatalError("TimelineItem \(itemID) not found") - } - - guard let voiceMessageRoomTimelineItem = timelineItem as? VoiceMessageRoomTimelineItem else { - fatalError("Invalid TimelineItem type for itemID \(itemID) (expecting `VoiceMessageRoomTimelineItem` but found \(type(of: timelineItem)) instead") - } - - guard let source = voiceMessageRoomTimelineItem.content.source else { - MXLog.error("Cannot start voice message playback, source is not defined for itemID \(itemID)") - 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 - } - - // Stop any recording in progress - if voiceMessageRecorder.isRecording { - await voiceMessageRecorder.stopRecording() - } - - guard let audioPlayerState = audioPlayerState(for: itemID) else { - fatalError("Audio player state not found for \(itemID)") - } - - // Ensure this one is attached - if !audioPlayerState.isAttached { - audioPlayerState.attachAudioPlayer(audioPlayer) - } - - // Detach all other states - await mediaPlayerProvider.detachAllStates(except: audioPlayerState) - - guard audioPlayer.mediaSource == source, audioPlayer.state != .error else { - // Load content - do { - MXLog.info("Loading voice message audio content from source for itemID \(itemID)") - let url = try await voiceMessageMediaManager.loadVoiceMessageFromSource(source, body: nil) - - // 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) - } - } catch { - MXLog.error("Failed to load voice message: \(error)") - audioPlayerState.reportError() - } - - return - } - - if audioPlayer.state == .playing { - audioPlayer.pause() - } else { - audioPlayer.play() - } - } - - func seekAudio(for itemID: TimelineItemIdentifier, progress: Double) async { - guard let playerState = mediaPlayerProvider.playerState(for: .timelineItemIdentifier(itemID)) else { - return - } - await mediaPlayerProvider.detachAllStates(except: playerState) - await playerState.updateState(progress: progress) - } - - func audioPlayerState(for itemID: TimelineItemIdentifier) -> AudioPlayerState? { - guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID) else { - MXLog.error("TimelineItem \(itemID) not found") - return nil - } - - guard let voiceMessageRoomTimelineItem = timelineItem as? VoiceMessageRoomTimelineItem else { - MXLog.error("Invalid TimelineItem type (expecting `VoiceMessageRoomTimelineItem` but found \(type(of: timelineItem)) instead") - return nil - } - - if let playerState = mediaPlayerProvider.playerState(for: .timelineItemIdentifier(itemID)) { - return playerState - } - - let playerState = AudioPlayerState(id: .timelineItemIdentifier(itemID), - duration: voiceMessageRoomTimelineItem.content.duration, - waveform: voiceMessageRoomTimelineItem.content.waveform) - mediaPlayerProvider.register(audioPlayerState: playerState) - return playerState - } - - // MARK: Other - - func displayEmojiPicker(for itemID: TimelineItemIdentifier) { - guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID), - timelineItem.isReactable, - let eventTimelineItem = timelineItem as? EventBasedTimelineItemProtocol else { - return - } - let selectedEmojis = Set(eventTimelineItem.properties.reactions.compactMap { $0.isHighlighted ? $0.key : nil }) - actionsSubject.send(.displayEmojiPicker(itemID: itemID, selectedEmojis: selectedEmojis)) - } - - func displayRoomMemberDetails(userID: String) async { - actionsSubject.send(.displayRoomMemberDetails(userID: userID)) - } - - func processItemTap(_ itemID: TimelineItemIdentifier) async -> RoomTimelineControllerAction { - guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID) else { - return .none - } - - switch timelineItem { - case let item as LocationRoomTimelineItem: - guard let geoURI = item.content.geoURI else { return .none } - return .displayLocation(body: item.content.body, geoURI: geoURI, description: item.content.description) - default: - return await displayMediaActionIfPossible(timelineItem: timelineItem) - } - } - - // MARK: - Private - - private func buildReplyInfo(for item: EventBasedTimelineItemProtocol) -> ReplyInfo { - switch item { - case let messageItem as EventBasedMessageTimelineItemProtocol: - return .init(type: .message(messageItem.contentType), isThread: messageItem.isThreaded) - case let pollItem as PollRoomTimelineItem: - return .init(type: .poll(question: pollItem.poll.question), isThread: false) - default: - return .init(type: .message(.text(.init(body: item.body))), isThread: false) - } - } - - private func displayMediaActionIfPossible(timelineItem: RoomTimelineItemProtocol) async -> RoomTimelineControllerAction { - var source: MediaSourceProxy? - var body: String - - switch timelineItem { - case let item as ImageRoomTimelineItem: - source = item.content.source - body = item.content.body - case let item as VideoRoomTimelineItem: - source = item.content.source - body = item.content.body - case let item as FileRoomTimelineItem: - source = item.content.source - body = item.content.body - case let item as AudioRoomTimelineItem: - // For now we are just displaying audio messages with the File preview until we create a timeline player for them. - source = item.content.source - body = item.content.body - default: - return .none - } - - guard let source else { return .none } - switch await mediaProvider.loadFileFromSource(source, body: body) { - case .success(let file): - return .displayMediaFile(file: file, title: body) - case .failure: - return .none - } - } -} - -private struct ReplyInfo { - let type: TimelineEventContent - let isThread: Bool -} diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift index 550ffdecba..cd2d31f02c 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift @@ -1,356 +1,48 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // -import Combine +import Foundation import OrderedCollections -import SwiftUI enum RoomScreenViewModelAction { - case displayRoomDetails - case displayEmojiPicker(itemID: TimelineItemIdentifier, selectedEmojis: Set) - case displayReportContent(itemID: TimelineItemIdentifier, senderID: String) - case displayCameraPicker - case displayMediaPicker - case displayDocumentPicker - case displayLocationPicker - case displayPollForm(mode: PollFormMode) - case displayMediaUploadPreviewScreen(url: URL) - case displayRoomMemberDetails(userID: String) - case displayMessageForwarding(forwardingItem: MessageForwardingItem) - case displayLocation(body: String, geoURI: GeoURI, description: String?) - case composer(action: RoomScreenComposerAction) - case displayCallScreen + case focusEvent(eventID: String) case displayPinnedEventsTimeline -} - -enum RoomScreenComposerMode: Equatable { - case `default` - case reply(itemID: TimelineItemIdentifier, replyDetails: TimelineItemReplyDetails, isThread: Bool) - case edit(originalItemId: TimelineItemIdentifier) - case recordVoiceMessage(state: AudioRecorderState) - case previewVoiceMessage(state: AudioPlayerState, waveform: WaveformSource, isUploading: Bool) - - var isEdit: Bool { - switch self { - case .edit: - return true - default: - return false - } - } - - var isTextEditingEnabled: Bool { - switch self { - case .default, .reply, .edit: - return true - case .recordVoiceMessage, .previewVoiceMessage: - return false - } - } - - var isLoadingReply: Bool { - switch self { - case .reply(_, let replyDetails, _): - switch replyDetails { - case .loading: - return true - default: - return false - } - default: - return false - } - } - - var replyEventID: String? { - switch self { - case .reply(let itemID, _, _): - return itemID.eventID - default: - return nil - } - } - - var isComposingNewMessage: Bool { - switch self { - case .default, .reply: - return true - default: - return false - } - } -} - -enum RoomScreenViewPollAction { - case selectOption(pollStartID: String, optionID: String) - case end(pollStartID: String) - case edit(pollStartID: String, poll: Poll) -} - -enum RoomScreenAudioPlayerAction { - case playPause(itemID: TimelineItemIdentifier) - case seek(itemID: TimelineItemIdentifier, progress: Double) + case displayRoomDetails + case displayCall + case removeComposerFocus } enum RoomScreenViewAction { - case itemAppeared(itemID: TimelineItemIdentifier) - case itemDisappeared(itemID: TimelineItemIdentifier) - - case itemTapped(itemID: TimelineItemIdentifier) - case itemSendInfoTapped(itemID: TimelineItemIdentifier) - case toggleReaction(key: String, itemID: TimelineItemIdentifier) - case sendReadReceiptIfNeeded(TimelineItemIdentifier) - case paginateBackwards - case paginateForwards - case scrollToBottom - - case displayTimelineItemMenu(itemID: TimelineItemIdentifier) - case handleTimelineItemMenuAction(itemID: TimelineItemIdentifier, action: TimelineItemMenuAction) - - case displayRoomDetails - case displayRoomMemberDetails(userID: String) - case displayReactionSummary(itemID: TimelineItemIdentifier, key: String) - case displayEmojiPicker(itemID: TimelineItemIdentifier) - case displayReadReceipts(itemID: TimelineItemIdentifier) - case displayCall - - case handlePasteOrDrop(provider: NSItemProvider) - case handlePollAction(RoomScreenViewPollAction) - case handleAudioPlayerAction(RoomScreenAudioPlayerAction) - - /// Focus the timeline onto the specified event ID (switching to a detached timeline if needed). - case focusOnEventID(String) - /// Switch back to a live timeline (from a detached one). - case focusLive - /// The timeline scrolled to reveal the focussed item. - case scrolledToFocussedItem - /// The table view has loaded the first items for a new timeline. - case hasSwitchedTimeline - - case hasScrolled(direction: ScrollDirection) case tappedPinnedEventsBanner case viewAllPins -} - -enum RoomScreenComposerAction { - case setMode(mode: RoomScreenComposerMode) - case setText(plainText: String, htmlText: String?) - case removeFocus - case clear - case saveDraft - case loadDraft + case displayRoomDetails + case displayCall } struct RoomScreenViewState: BindableState { - var roomID: String var roomTitle = "" var roomAvatar: RoomAvatar - var members: [String: RoomMemberState] = [:] - var typingMembers: [String] = [] - var showLoading = false - var showReadReceipts = false - var isEncryptedOneToOneRoom = false - var timelineViewState: TimelineViewState // check the doc before changing this - - var ownUserID: String - var canCurrentUserRedactOthers = false - var canCurrentUserRedactSelf = false - var canCurrentUserPin = false - var isViewSourceEnabled: Bool - var isPinningEnabled = false var lastScrollDirection: ScrollDirection? - - // The `pinnedEventIDs` are used only to determine if an item is already pinned or not. - // It's updated from the room info, so it's faster than using the timeline - var pinnedEventIDs: Set = [] + var isPinningEnabled = false // This is used to control the banner var pinnedEventsBannerState: PinnedEventsBannerState = .loading(numbersOfEvents: 0) - var shouldShowPinnedEventsBanner: Bool { isPinningEnabled && !pinnedEventsBannerState.isEmpty && lastScrollDirection != .top } var canJoinCall = false - var hasOngoingCall = false + var hasOngoingCall: Bool + var shouldShowCallButton = true var bindings: RoomScreenViewStateBindings - - /// A closure providing the associated audio player state for an item in the timeline. - var audioPlayerStateProvider: (@MainActor (_ itemId: TimelineItemIdentifier) -> AudioPlayerState?)? -} - -struct RoomScreenViewStateBindings { - var isScrolledToBottom = true - - /// The state of wether reactions listed on the timeline are expanded/collapsed. - /// Key is itemID, value is the collapsed state. - var reactionsCollapsed: [TimelineItemIdentifier: Bool] - - /// A media item that will be previewed with QuickLook. - var mediaPreviewItem: MediaPreviewItem? - - var alertInfo: AlertInfo? - - var debugInfo: TimelineItemDebugInfo? - - var actionMenuInfo: TimelineItemActionMenuInfo? - - var reactionSummaryInfo: ReactionSummaryInfo? - - var readReceiptsSummaryInfo: ReadReceiptSummaryInfo? -} - -struct TimelineItemActionMenuInfo: Equatable, Identifiable { - static func == (lhs: TimelineItemActionMenuInfo, rhs: TimelineItemActionMenuInfo) -> Bool { - lhs.id == rhs.id - } - - let item: EventBasedTimelineItemProtocol - - var id: TimelineItemIdentifier { - item.id - } -} - -struct ReactionSummaryInfo: Identifiable { - let reactions: [AggregatedReaction] - let selectedKey: String - - var id: String { - selectedKey - } -} - -struct ReadReceiptSummaryInfo: Identifiable { - let orderedReceipts: [ReadReceipt] - let id: TimelineItemIdentifier -} - -enum RoomScreenAlertInfoType: Hashable { - case audioRecodingPermissionError - case pollEndConfirmation(String) - case sendingFailed - case encryptionAuthenticity(String) -} - -struct RoomMemberState { - let displayName: String? - let avatarURL: URL? -} - -/// Used as the state for the TimelineView, to avoid having the context continuously refresh the list of items on each small change. -/// Is also nice to have this as a wrapper for any state that is directly connected to the timeline. -struct TimelineViewState { - var isLive = true - var paginationState = PaginationState.initial - - /// The room is in the process of loading items from a new timeline (switching to/from a detached timeline). - var isSwitchingTimelines = false - - struct FocussedEvent: Equatable { - enum Appearance { - /// The event should be shown using an animated scroll. - case animated - /// The event should be shown immediately, without any animation. - case immediate - /// The event has already been shown. - case hasAppeared - } - - /// The ID of the event. - let eventID: String - /// How the event should be shown, or whether it has already appeared. - var appearance: Appearance - } - - /// A focussed event that was navigated to via a permalink. - var focussedEvent: FocussedEvent? - - // These can be removed when we have full swiftUI and moved as @State values in the view - var scrollToBottomPublisher = PassthroughSubject() - - var itemsDictionary = OrderedDictionary() - - var timelineIDs: [String] { - itemsDictionary.keys.elements - } - - var itemViewStates: [RoomTimelineItemViewState] { - itemsDictionary.values.elements - } - - func hasLoadedItem(with eventID: String) -> Bool { - itemViewStates.contains { $0.identifier.eventID == eventID } - } -} - -enum ScrollDirection: Equatable { - case top - case bottom } -struct PinnedEventsState: Equatable { - var pinnedEventContents: OrderedDictionary = [:] { - didSet { - if selectedPinEventID == nil, !pinnedEventContents.keys.isEmpty { - // The default selected event should always be the last one. - selectedPinEventID = pinnedEventContents.keys.last - } else if pinnedEventContents.isEmpty { - selectedPinEventID = nil - } else if let selectedPinEventID, !pinnedEventContents.keys.set.contains(selectedPinEventID) { - self.selectedPinEventID = pinnedEventContents.keys.last - } - } - } - - private(set) var selectedPinEventID: String? - - var selectedPinIndex: Int { - let defaultValue = pinnedEventContents.isEmpty ? 0 : pinnedEventContents.count - 1 - guard let selectedPinEventID else { - return defaultValue - } - return pinnedEventContents.keys.firstIndex(of: selectedPinEventID) ?? defaultValue - } - - var selectedPinContent: AttributedString { - var content = AttributedString(" ") - if let selectedPinEventID, - let pinnedEventContent = pinnedEventContents[selectedPinEventID] { - content = pinnedEventContent - } - content.font = .compound.bodyMD - content.link = nil - return content - } - - mutating func previousPin() { - guard !pinnedEventContents.isEmpty else { - return - } - let currentIndex = selectedPinIndex - let nextIndex = currentIndex - 1 - if nextIndex == -1 { - selectedPinEventID = pinnedEventContents.keys.last - } else { - selectedPinEventID = pinnedEventContents.keys[nextIndex % pinnedEventContents.count] - } - } -} +struct RoomScreenViewStateBindings { } enum PinnedEventsBannerState: Equatable { case loading(numbersOfEvents: Int) @@ -374,10 +66,10 @@ enum PinnedEventsBannerState: Equatable { } } - var selectedPinEventID: String? { + var selectedPinnedEventID: String? { switch self { case .loaded(let state): - return state.selectedPinEventID + return state.selectedPinnedEventID default: return nil } @@ -392,10 +84,10 @@ enum PinnedEventsBannerState: Equatable { } } - var selectedPinIndex: Int { + var selectedPinnedIndex: Int { switch self { case .loaded(let state): - return state.selectedPinIndex + return state.selectedPinnedIndex case .loading(let numbersOfEvents): // We always want the index to be the last one when loading, since is the default one. return numbersOfEvents - 1 @@ -407,12 +99,12 @@ enum PinnedEventsBannerState: Equatable { case .loading: return AttributedString(L10n.screenRoomPinnedBannerLoadingDescription) case .loaded(let state): - return state.selectedPinContent + return state.selectedPinnedContent } } var bannerIndicatorDescription: AttributedString { - let index = selectedPinIndex + 1 + let index = selectedPinnedIndex + 1 let boldPlaceholder = "{bold}" var finalString = AttributedString(L10n.screenRoomPinnedBannerIndicatorDescription(boldPlaceholder)) var boldString = AttributedString(L10n.screenRoomPinnedBannerIndicator(index, count)) @@ -435,10 +127,72 @@ enum PinnedEventsBannerState: Equatable { switch self { case .loading: // The default selected event should always be the last one. - self = .loaded(state: .init(pinnedEventContents: pinnedEventContents, selectedPinEventID: pinnedEventContents.keys.last)) + self = .loaded(state: .init(pinnedEventContents: pinnedEventContents, selectedPinnedEventID: pinnedEventContents.keys.last)) case .loaded(var state): state.pinnedEventContents = pinnedEventContents self = .loaded(state: state) } } + + // Note that if we are setting this value, this is definitely sent from the pinned events timeline + // so we can assume that the pinned events timeline is already loaded and we only need to set the + // selection for the loaded state + mutating func setSelectedPinnedEventID(_ eventID: String) { + switch self { + case .loaded(var state): + state.selectedPinnedEventID = eventID + self = .loaded(state: state) + case .loading: + break + } + } +} + +struct PinnedEventsState: Equatable { + var pinnedEventContents: OrderedDictionary = [:] { + didSet { + if selectedPinnedEventID == nil, !pinnedEventContents.keys.isEmpty { + // The default selected event should always be the last one. + selectedPinnedEventID = pinnedEventContents.keys.last + } else if pinnedEventContents.isEmpty { + selectedPinnedEventID = nil + } else if let selectedPinnedEventID, !pinnedEventContents.keys.set.contains(selectedPinnedEventID) { + self.selectedPinnedEventID = pinnedEventContents.keys.last + } + } + } + + var selectedPinnedEventID: String? + + var selectedPinnedIndex: Int { + let defaultValue = pinnedEventContents.isEmpty ? 0 : pinnedEventContents.count - 1 + guard let selectedPinnedEventID else { + return defaultValue + } + return pinnedEventContents.keys.firstIndex(of: selectedPinnedEventID) ?? defaultValue + } + + var selectedPinnedContent: AttributedString { + var content = AttributedString(" ") + if let selectedPinnedEventID, + let pinnedEventContent = pinnedEventContents[selectedPinnedEventID] { + content = pinnedEventContent + } + content.font = .compound.bodyMD + content.link = nil + return content + } + + mutating func previousPin() { + guard !pinnedEventContents.isEmpty else { + return + } + let currentIndex = selectedPinnedIndex + let nextIndex = currentIndex - 1 + if nextIndex == -1 { + selectedPinnedEventID = pinnedEventContents.keys.last + } else { + selectedPinnedEventID = pinnedEventContents.keys[nextIndex % pinnedEventContents.count] + } + } } diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift index 309bca1a76..8c33e3e3ad 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift @@ -1,430 +1,104 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // -import Algorithms import Combine +import Foundation import OrderedCollections import SwiftUI typealias RoomScreenViewModelType = StateStoreViewModel class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol { - private enum Constants { - static let paginationEventLimit: UInt16 = 20 - static let detachedTimelineSize: UInt16 = 100 - static let focusTimelineToastIndicatorID = "RoomScreenFocusTimelineToastIndicator" - static let toastErrorID = "RoomScreenToastError" - } - - private let roomProxy: RoomProxyProtocol - private let timelineController: RoomTimelineControllerProtocol - private let mediaPlayerProvider: MediaPlayerProviderProtocol - private let userIndicatorController: UserIndicatorControllerProtocol + private let roomProxy: JoinedRoomProxyProtocol private let appMediator: AppMediatorProtocol private let appSettings: AppSettings private let analyticsService: AnalyticsService private let pinnedEventStringBuilder: RoomEventStringBuilder - - private let roomScreenInteractionHandler: RoomScreenInteractionHandler - - private let composerFocusedSubject = PassthroughSubject() + private var initialSelectedPinnedEventID: String? private let actionsSubject: PassthroughSubject = .init() var actions: AnyPublisher { actionsSubject.eraseToAnyPublisher() } - private var paginateBackwardsTask: Task? - private var paginateForwardsTask: Task? - private var pinnedEventsTimelineProvider: RoomTimelineProviderProtocol? { didSet { guard let pinnedEventsTimelineProvider else { return } - buildPinnedEventContent(timelineItems: pinnedEventsTimelineProvider.itemProxies) + buildPinnedEventContents(timelineItems: pinnedEventsTimelineProvider.itemProxies) pinnedEventsTimelineProvider.updatePublisher // When pinning or unpinning an item, the timeline might return empty for a short while, so we need to debounce it to prevent weird UI behaviours like the banner disappearing .debounce(for: .milliseconds(100), scheduler: DispatchQueue.main) .sink { [weak self] updatedItems, _ in guard let self else { return } - buildPinnedEventContent(timelineItems: updatedItems) + buildPinnedEventContents(timelineItems: updatedItems) } .store(in: &cancellables) } } - - init(roomProxy: RoomProxyProtocol, - focussedEventID: String? = nil, - timelineController: RoomTimelineControllerProtocol, + + init(roomProxy: JoinedRoomProxyProtocol, + initialSelectedPinnedEventID: String?, mediaProvider: MediaProviderProtocol, - mediaPlayerProvider: MediaPlayerProviderProtocol, - voiceMessageMediaManager: VoiceMessageMediaManagerProtocol, - userIndicatorController: UserIndicatorControllerProtocol, + ongoingCallRoomIDPublisher: CurrentValuePublisher, appMediator: AppMediatorProtocol, appSettings: AppSettings, analyticsService: AnalyticsService) { - self.timelineController = timelineController - self.mediaPlayerProvider = mediaPlayerProvider self.roomProxy = roomProxy + self.appMediator = appMediator self.appSettings = appSettings self.analyticsService = analyticsService - self.userIndicatorController = userIndicatorController - self.appMediator = appMediator + self.initialSelectedPinnedEventID = initialSelectedPinnedEventID pinnedEventStringBuilder = .pinnedEventStringBuilder(userID: roomProxy.ownUserID) - - let voiceMessageRecorder = VoiceMessageRecorder(audioRecorder: AudioRecorder(), mediaPlayerProvider: mediaPlayerProvider) - - roomScreenInteractionHandler = RoomScreenInteractionHandler(roomProxy: roomProxy, - timelineController: timelineController, - mediaProvider: mediaProvider, - mediaPlayerProvider: mediaPlayerProvider, - voiceMessageMediaManager: voiceMessageMediaManager, - voiceMessageRecorder: voiceMessageRecorder, - userIndicatorController: userIndicatorController, - appMediator: appMediator, - appSettings: appSettings, - analyticsService: analyticsService) - - super.init(initialViewState: RoomScreenViewState(roomID: roomProxy.id, - roomTitle: roomProxy.roomTitle, - roomAvatar: roomProxy.avatar, - isEncryptedOneToOneRoom: roomProxy.isEncryptedOneToOneRoom, - timelineViewState: TimelineViewState(focussedEvent: focussedEventID.map { .init(eventID: $0, appearance: .immediate) }), - ownUserID: roomProxy.ownUserID, - isViewSourceEnabled: appSettings.viewSourceEnabled, - hasOngoingCall: roomProxy.hasOngoingCall, - bindings: .init(reactionsCollapsed: [:])), - imageProvider: mediaProvider) - - if focussedEventID != nil { - // The timeline controller will start loading a detached timeline. - showFocusLoadingIndicator() - } - - setupSubscriptions() - setupDirectRoomSubscriptionsIfNeeded() - - // Set initial values for redacting from the macOS context menu. - Task { await updatePermissions() } - state.audioPlayerStateProvider = { [weak self] itemID -> AudioPlayerState? in - guard let self else { - return nil - } - - return self.roomScreenInteractionHandler.audioPlayerState(for: itemID) - } - - buildTimelineViews(timelineItems: timelineController.timelineItems) - - updateMembers(roomProxy.membersPublisher.value) - - // Note: beware if we get to e.g. restore a reply / edit, - // maybe we are tracking a non-needed first initial state - trackComposerMode(.default) + super.init(initialViewState: .init(roomTitle: roomProxy.roomTitle, + roomAvatar: roomProxy.avatar, + hasOngoingCall: roomProxy.hasOngoingCall, + bindings: .init()), + mediaProvider: mediaProvider) Task { - let userID = roomProxy.ownUserID - if case let .success(permission) = await roomProxy.canUserJoinCall(userID: userID) { - state.canJoinCall = permission - } + await handleRoomInfoUpdate() } + + setupSubscriptions(ongoingCallRoomIDPublisher: ongoingCallRoomIDPublisher) } - - // MARK: - Public - - func loadDraft() { - actionsSubject.send(.composer(action: .loadDraft)) - } - - func stop() { - // Work around QLPreviewController dismissal issues, see the InteractiveQuickLookModifier. - state.bindings.mediaPreviewItem = nil - } - - func saveDraft() { - actionsSubject.send(.composer(action: .saveDraft)) - } - + override func process(viewAction: RoomScreenViewAction) { switch viewAction { - case .itemAppeared(let id): - Task { await timelineController.processItemAppearance(id) } - case .itemDisappeared(let id): - Task { await timelineController.processItemDisappearance(id) } - - case .itemTapped(let id): - Task { await handleItemTapped(with: id) } - case .itemSendInfoTapped(let itemID): - handleItemSendInfoTapped(itemID: itemID) - case .toggleReaction(let emoji, let itemId): - Task { await timelineController.toggleReaction(emoji, to: itemId) } - case .sendReadReceiptIfNeeded(let lastVisibleItemID): - Task { await sendReadReceiptIfNeeded(for: lastVisibleItemID) } - case .paginateBackwards: - paginateBackwards() - case .paginateForwards: - paginateForwards() - case .scrollToBottom: - scrollToBottom() - - case .displayTimelineItemMenu(let itemID): - roomScreenInteractionHandler.displayTimelineItemActionMenu(for: itemID) - case .handleTimelineItemMenuAction(let itemID, let action): - roomScreenInteractionHandler.handleTimelineItemMenuAction(action, itemID: itemID) - - case .displayRoomDetails: - actionsSubject.send(.displayRoomDetails) - case .displayRoomMemberDetails(userID: let userID): - Task { await roomScreenInteractionHandler.displayRoomMemberDetails(userID: userID) } - case .displayEmojiPicker(let itemID): - roomScreenInteractionHandler.displayEmojiPicker(for: itemID) - case .displayReactionSummary(let itemID, let key): - displayReactionSummary(for: itemID, selectedKey: key) - case .displayReadReceipts(itemID: let itemID): - displayReadReceipts(for: itemID) - case .displayCall: - actionsSubject.send(.displayCallScreen) - analyticsService.trackInteraction(name: .MobileRoomCallButton) - case .handlePasteOrDrop(let provider): - roomScreenInteractionHandler.handlePasteOrDrop(provider) - case .handlePollAction(let pollAction): - handlePollAction(pollAction) - case .handleAudioPlayerAction(let audioPlayerAction): - handleAudioPlayerAction(audioPlayerAction) - - case .focusOnEventID(let eventID): - Task { await focusOnEvent(eventID: eventID) } - case .focusLive: - focusLive() - case .scrolledToFocussedItem: - didScrollToFocussedItem() - case .hasSwitchedTimeline: - Task { state.timelineViewState.isSwitchingTimelines = false } - case let .hasScrolled(direction): - state.lastScrollDirection = direction case .tappedPinnedEventsBanner: - if let eventID = state.pinnedEventsBannerState.selectedPinEventID { - Task { await focusOnEvent(eventID: eventID) } + analyticsService.trackInteraction(name: .PinnedMessageBannerClick) + if let eventID = state.pinnedEventsBannerState.selectedPinnedEventID { + actionsSubject.send(.focusEvent(eventID: eventID)) } state.pinnedEventsBannerState.previousPin() case .viewAllPins: + analyticsService.trackInteraction(name: .PinnedMessageBannerViewAllButton) actionsSubject.send(.displayPinnedEventsTimeline) - } - } - - func process(composerAction: ComposerToolbarViewModelAction) { - switch composerAction { - case .sendMessage(let message, let html, let mode, let intentionalMentions): - Task { - await sendCurrentMessage(message, - html: html, - mode: mode, - intentionalMentions: intentionalMentions) - } - case .editLastMessage: - editLastMessage() - case .attach(let attachment): - attach(attachment) - case .handlePasteOrDrop(let provider): - roomScreenInteractionHandler.handlePasteOrDrop(provider) - case .composerModeChanged(mode: let mode): - trackComposerMode(mode) - case .composerFocusedChanged(isFocused: let isFocused): - composerFocusedSubject.send(isFocused) - case .voiceMessage(let voiceMessageAction): - processVoiceMessageAction(voiceMessageAction) - case .contentChanged(let isEmpty): - guard appSettings.sharePresence else { - return - } - - Task { - await roomProxy.sendTypingNotification(isTyping: !isEmpty) - } - } - } - - func focusOnEvent(eventID: String) async { - if state.timelineViewState.hasLoadedItem(with: eventID) { - state.timelineViewState.focussedEvent = .init(eventID: eventID, appearance: .animated) - return - } - - showFocusLoadingIndicator() - defer { hideFocusLoadingIndicator() } - - switch await timelineController.focusOnEvent(eventID, timelineSize: Constants.detachedTimelineSize) { - case .success: - state.timelineViewState.focussedEvent = .init(eventID: eventID, appearance: .immediate) - case .failure(let error): - MXLog.error("Failed to focus on event \(eventID)") - - if case .eventNotFound = error { - displayErrorToast(L10n.errorMessageNotFound) - } else { - displayErrorToast(L10n.commonFailed) - } - } - } - - // MARK: - Private - - private func focusLive() { - timelineController.focusLive() - } - - private func didScrollToFocussedItem() { - if var focussedEvent = state.timelineViewState.focussedEvent { - focussedEvent.appearance = .hasAppeared - state.timelineViewState.focussedEvent = focussedEvent - hideFocusLoadingIndicator() - } - } - - private func editLastMessage() { - guard let item = timelineController.timelineItems.reversed().first(where: { - guard let item = $0 as? EventBasedMessageTimelineItemProtocol else { - return false - } - - return item.sender.id == roomProxy.ownUserID && item.isEditable - }) else { - return - } - - roomScreenInteractionHandler.handleTimelineItemMenuAction(.edit, itemID: item.id) - } - - private func attach(_ attachment: ComposerAttachmentType) { - switch attachment { - case .camera: - actionsSubject.send(.displayCameraPicker) - case .photoLibrary: - actionsSubject.send(.displayMediaPicker) - case .file: - actionsSubject.send(.displayDocumentPicker) - case .location: - actionsSubject.send(.displayLocationPicker) - case .poll: - actionsSubject.send(.displayPollForm(mode: .new)) - } - } - - private func handlePollAction(_ action: RoomScreenViewPollAction) { - switch action { - case let .selectOption(pollStartID, optionID): - roomScreenInteractionHandler.sendPollResponse(pollStartID: pollStartID, optionID: optionID) - case let .end(pollStartID): - displayAlert(.pollEndConfirmation(pollStartID)) - case .edit(let pollStartID, let poll): - actionsSubject.send(.displayPollForm(mode: .edit(eventID: pollStartID, poll: poll))) - } - } - - private func handleAudioPlayerAction(_ action: RoomScreenAudioPlayerAction) { - switch action { - case .playPause(let itemID): - Task { await roomScreenInteractionHandler.playPauseAudio(for: itemID) } - case .seek(let itemID, let progress): - Task { await roomScreenInteractionHandler.seekAudio(for: itemID, progress: progress) } + case .displayRoomDetails: + actionsSubject.send(.displayRoomDetails) + case .displayCall: + actionsSubject.send(.displayCall) + actionsSubject.send(.removeComposerFocus) + analyticsService.trackInteraction(name: .MobileRoomCallButton) } } - private func processVoiceMessageAction(_ action: ComposerToolbarVoiceMessageAction) { - switch action { - case .startRecording: - Task { - await mediaPlayerProvider.detachAllStates(except: nil) - await roomScreenInteractionHandler.startRecordingVoiceMessage() - } - case .stopRecording: - Task { await roomScreenInteractionHandler.stopRecordingVoiceMessage() } - case .cancelRecording: - Task { await roomScreenInteractionHandler.cancelRecordingVoiceMessage() } - case .deleteRecording: - Task { await roomScreenInteractionHandler.deleteCurrentVoiceMessage() } - case .send: - Task { await roomScreenInteractionHandler.sendCurrentVoiceMessage() } - case .startPlayback: - Task { await roomScreenInteractionHandler.startPlayingRecordedVoiceMessage() } - case .pausePlayback: - roomScreenInteractionHandler.pausePlayingRecordedVoiceMessage() - case .seekPlayback(let progress): - Task { await roomScreenInteractionHandler.seekRecordedVoiceMessage(to: progress) } - case .scrubPlayback(let scrubbing): - Task { await roomScreenInteractionHandler.scrubVoiceMessagePlayback(scrubbing: scrubbing) } - } + func timelineHasScrolled(direction: ScrollDirection) { + state.lastScrollDirection = direction } - private func updateMembers(_ members: [RoomMemberProxyProtocol]) { - state.members = members.reduce(into: [String: RoomMemberState]()) { dictionary, member in - dictionary[member.userID] = RoomMemberState(displayName: member.displayName, avatarURL: member.avatarURL) - } + func setSelectedPinnedEventID(_ eventID: String) { + state.pinnedEventsBannerState.setSelectedPinnedEventID(eventID) } - private func updatePermissions() async { - if case let .success(value) = await roomProxy.canUserRedactOther(userID: roomProxy.ownUserID) { - state.canCurrentUserRedactOthers = value - } else { - state.canCurrentUserRedactOthers = false - } - - if case let .success(value) = await roomProxy.canUserRedactOwn(userID: roomProxy.ownUserID) { - state.canCurrentUserRedactSelf = value - } else { - state.canCurrentUserRedactSelf = false - } - - if state.isPinningEnabled, - case let .success(value) = await roomProxy.canUserPinOrUnpin(userID: roomProxy.ownUserID) { - state.canCurrentUserPin = value - } else { - state.canCurrentUserPin = false - } - } - - private func setupSubscriptions() { - timelineController.callbacks - .receive(on: DispatchQueue.main) - .sink { [weak self] callback in - guard let self else { return } - - switch callback { - case .updatedTimelineItems(let updatedItems, let isSwitchingTimelines): - buildTimelineViews(timelineItems: updatedItems, isSwitchingTimelines: isSwitchingTimelines) - case .paginationState(let paginationState): - if state.timelineViewState.paginationState != paginationState { - state.timelineViewState.paginationState = paginationState - } - case .isLive(let isLive): - if state.timelineViewState.isLive != isLive { - state.timelineViewState.isLive = isLive - - // Remove the event highlight *only* when transitioning from non-live to live. - if isLive, state.timelineViewState.focussedEvent != nil { - state.timelineViewState.focussedEvent = nil - } - } - } - } - .store(in: &cancellables) - + private func setupSubscriptions(ongoingCallRoomIDPublisher: CurrentValuePublisher) { let roomInfoSubscription = roomProxy .actionsPublisher .filter { $0 == .roomInfoUpdate } @@ -440,67 +114,23 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol .store(in: &cancellables) Task { [weak self] in - // Don't guard let self here, otherwise the for await will strongify the self reference creating a strong reference cycle. - // If the subscription has sent a value before the Task has started it might be lost, so before entering the loop we always do an update. - await self?.updatePinnedEventIDs() for await _ in roomInfoSubscription.receive(on: DispatchQueue.main).values { guard !Task.isCancelled else { return } - await self?.updatePinnedEventIDs() + + await self?.handleRoomInfoUpdate() } } .store(in: &cancellables) - setupAppSettingsSubscriptions() - - roomProxy.membersPublisher - .receive(on: DispatchQueue.main) - .sink { [weak self] in self?.updateMembers($0) } - .store(in: &cancellables) - - roomProxy.typingMembersPublisher - .receive(on: DispatchQueue.main) - .filter { [weak self] _ in self?.appSettings.sharePresence ?? false } - .weakAssign(to: \.state.typingMembers, on: self) - .store(in: &cancellables) + let pinningEnabledPublisher = appSettings.$pinningEnabled - roomScreenInteractionHandler.actions - .receive(on: DispatchQueue.main) - .sink { [weak self] action in - guard let self else { return } - - switch action { - case .composer(let action): - actionsSubject.send(.composer(action: action)) - case .displayAudioRecorderPermissionError: - displayAlert(.audioRecodingPermissionError) - case .displayErrorToast(let title): - displayErrorToast(title) - case .displayEmojiPicker(let itemID, let selectedEmojis): - actionsSubject.send(.displayEmojiPicker(itemID: itemID, selectedEmojis: selectedEmojis)) - case .displayMessageForwarding(let itemID): - Task { await self.forwardMessage(itemID: itemID) } - case .displayPollForm(let mode): - actionsSubject.send(.displayPollForm(mode: mode)) - case .displayReportContent(let itemID, let senderID): - actionsSubject.send(.displayReportContent(itemID: itemID, senderID: senderID)) - case .displayMediaUploadPreviewScreen(let url): - actionsSubject.send(.displayMediaUploadPreviewScreen(url: url)) - case .displayRoomMemberDetails(userID: let userID): - actionsSubject.send(.displayRoomMemberDetails(userID: userID)) - case .showActionMenu(let actionMenuInfo): - Task { - await self.updatePermissions() - self.state.bindings.actionMenuInfo = actionMenuInfo - } - case .showDebugInfo(let debugInfo): - state.bindings.debugInfo = debugInfo - } - } + pinningEnabledPublisher + .weakAssign(to: \.state.isPinningEnabled, on: self) .store(in: &cancellables) - appSettings.$pinningEnabled + pinningEnabledPublisher .combineLatest(appMediator.networkMonitor.reachabilityPublisher) .filter { $0.0 && $0.1 == .reachable } .receive(on: DispatchQueue.main) @@ -508,208 +138,17 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol self?.setupPinnedEventsTimelineProviderIfNeeded() } .store(in: &cancellables) - } - - private func setupAppSettingsSubscriptions() { - appSettings.$sharePresence - .weakAssign(to: \.state.showReadReceipts, on: self) - .store(in: &cancellables) - - appSettings.$viewSourceEnabled - .weakAssign(to: \.state.isViewSourceEnabled, on: self) - .store(in: &cancellables) - - appSettings.$pinningEnabled - .weakAssign(to: \.state.isPinningEnabled, on: self) - .store(in: &cancellables) - } - - private func setupPinnedEventsTimelineProviderIfNeeded() { - guard pinnedEventsTimelineProvider == nil else { - return - } - Task { - guard let timelineProvider = await roomProxy.pinnedEventsTimeline?.timelineProvider else { - return - } - - if pinnedEventsTimelineProvider == nil { - pinnedEventsTimelineProvider = timelineProvider - } - } - } - - private func updatePinnedEventIDs() async { - let pinnedEventIDs = await roomProxy.pinnedEventIDs - // Only update the loading state of the banner - if state.pinnedEventsBannerState.isLoading { - state.pinnedEventsBannerState = .loading(numbersOfEvents: pinnedEventIDs.count) - } - state.pinnedEventIDs = pinnedEventIDs - } - - private func setupDirectRoomSubscriptionsIfNeeded() { - guard roomProxy.isDirect else { - return - } - - let shouldShowInviteAlert = composerFocusedSubject - .removeDuplicates() - .map { [weak self] isFocused in - guard let self else { return false } - - return isFocused && self.roomProxy.isUserAloneInDirectRoom - } - // We want to show the alert just once, so we are taking the first "true" emitted - .first { $0 } - - shouldShowInviteAlert - .sink { [weak self] _ in - self?.showInviteAlert() + ongoingCallRoomIDPublisher + .receive(on: DispatchQueue.main) + .sink { [weak self] ongoingCallRoomID in + guard let self else { return } + state.shouldShowCallButton = ongoingCallRoomID != roomProxy.id } .store(in: &cancellables) } - - private func paginateBackwards() { - guard paginateBackwardsTask == nil else { - return - } - - paginateBackwardsTask = Task { [weak self] in - guard let self else { - return - } - - switch await timelineController.paginateBackwards(requestSize: Constants.paginationEventLimit) { - case .failure: - displayErrorToast(L10n.errorFailedLoadingMessages) - default: - break - } - paginateBackwardsTask = nil - } - } - - private func paginateForwards() { - guard paginateForwardsTask == nil else { - return - } - - paginateForwardsTask = Task { [weak self] in - guard let self else { - return - } - - switch await timelineController.paginateForwards(requestSize: Constants.paginationEventLimit) { - case .failure: - displayErrorToast(L10n.errorFailedLoadingMessages) - default: - break - } - - if state.timelineViewState.paginationState.forward == .timelineEndReached { - focusLive() - } - - paginateForwardsTask = nil - } - } - - private func scrollToBottom() { - if state.timelineViewState.isLive { - state.timelineViewState.scrollToBottomPublisher.send(()) - } else { - focusLive() - } - } - private func sendReadReceiptIfNeeded(for lastVisibleItemID: TimelineItemIdentifier) async { - guard appMediator.appState == .active else { return } - - await timelineController.sendReadReceipt(for: lastVisibleItemID) - } - - private func handleItemTapped(with itemID: TimelineItemIdentifier) async { - state.showLoading = true - let action = await roomScreenInteractionHandler.processItemTap(itemID) - - switch action { - case .displayMediaFile(let file, let title): - actionsSubject.send(.composer(action: .removeFocus)) // Hide the keyboard otherwise a big white space is sometimes shown when dismissing the preview. - state.bindings.mediaPreviewItem = MediaPreviewItem(file: file, title: title) - case .displayLocation(let body, let geoURI, let description): - actionsSubject.send(.displayLocation(body: body, geoURI: geoURI, description: description)) - case .none: - break - } - state.showLoading = false - } - - private func handleItemSendInfoTapped(itemID: TimelineItemIdentifier) { - guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID) else { - MXLog.warning("Couldn't find timeline item.") - return - } - - guard let eventTimelineItem = timelineItem as? EventBasedTimelineItemProtocol else { - fatalError("Only events can have send info.") - } - - if eventTimelineItem.properties.deliveryStatus == .sendingFailed { - displayAlert(.sendingFailed) - } else if let authenticityMessage = eventTimelineItem.properties.encryptionAuthenticity?.message { - displayAlert(.encryptionAuthenticity(authenticityMessage)) - } - } - - private func sendCurrentMessage(_ message: String, html: String?, mode: RoomScreenComposerMode, intentionalMentions: IntentionalMentions) async { - guard !message.isEmpty else { - fatalError("This message should never be empty") - } - - actionsSubject.send(.composer(action: .clear)) - - switch mode { - case .reply(let itemId, _, _): - await timelineController.sendMessage(message, - html: html, - inReplyTo: itemId, - intentionalMentions: intentionalMentions) - case .edit(let originalItemId): - await timelineController.edit(originalItemId, - message: message, - html: html, - intentionalMentions: intentionalMentions) - case .default: - await timelineController.sendMessage(message, - html: html, - intentionalMentions: intentionalMentions) - case .recordVoiceMessage, .previewVoiceMessage: - fatalError("invalid composer mode.") - } - - scrollToBottom() - } - - private func trackComposerMode(_ mode: RoomScreenComposerMode) { - var isEdit = false - var isReply = false - switch mode { - case .edit: - isEdit = true - case .reply: - isReply = true - default: - break - } - - analyticsService.trackComposer(inThread: false, isEditing: isEdit, isReply: isReply, startsThread: nil) - } - - // MARK: - Timeline Item Building - - private func buildPinnedEventContent(timelineItems: [TimelineItemProxy]) { + private func buildPinnedEventContents(timelineItems: [TimelineItemProxy]) { var pinnedEventContents = OrderedDictionary() for item in timelineItems { @@ -722,249 +161,64 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol } state.pinnedEventsBannerState.setPinnedEventContents(pinnedEventContents) - } - - private func buildTimelineViews(timelineItems: [RoomTimelineItemProtocol], isSwitchingTimelines: Bool = false) { - var timelineItemsDictionary = OrderedDictionary() - timelineItems.filter { $0 is RedactedRoomTimelineItem }.forEach { timelineItem in - // Stops the audio player when a voice message is redacted. - guard let playerState = mediaPlayerProvider.playerState(for: .timelineItemIdentifier(timelineItem.id)) else { - return - } - - Task { @MainActor in - playerState.detachAudioPlayer() - mediaPlayerProvider.unregister(audioPlayerState: playerState) - } - } - - let itemsGroupedByTimelineDisplayStyle = timelineItems.chunked { current, next in - canGroupItem(timelineItem: current, with: next) + // If it's the first time we are setting the pinned events, we should select the initial event if available. + if let initialSelectedPinnedEventID { + state.pinnedEventsBannerState.setSelectedPinnedEventID(initialSelectedPinnedEventID) + self.initialSelectedPinnedEventID = nil } - - for itemGroup in itemsGroupedByTimelineDisplayStyle { - guard !itemGroup.isEmpty else { - MXLog.error("Found empty item group") - continue - } - - if itemGroup.count == 1 { - if let firstItem = itemGroup.first { - timelineItemsDictionary.updateValue(updateViewState(item: firstItem, groupStyle: .single), - forKey: firstItem.id.timelineID) - } - } else { - for (index, item) in itemGroup.enumerated() { - if index == 0 { - timelineItemsDictionary.updateValue(updateViewState(item: item, groupStyle: .first), - forKey: item.id.timelineID) - } else if index == itemGroup.count - 1 { - timelineItemsDictionary.updateValue(updateViewState(item: item, groupStyle: .last), - forKey: item.id.timelineID) - } else { - timelineItemsDictionary.updateValue(updateViewState(item: item, groupStyle: .middle), - forKey: item.id.timelineID) - } - } - } - } - - if isSwitchingTimelines { - state.timelineViewState.isSwitchingTimelines = true - } - - state.timelineViewState.itemsDictionary = timelineItemsDictionary } - - private func updateViewState(item: RoomTimelineItemProtocol, groupStyle: TimelineGroupStyle) -> RoomTimelineItemViewState { - if let timelineItemViewState = state.timelineViewState.itemsDictionary[item.id.timelineID] { - timelineItemViewState.groupStyle = groupStyle - timelineItemViewState.type = .init(item: item) - return timelineItemViewState - } else { - return RoomTimelineItemViewState(item: item, groupStyle: groupStyle) - } - } - - private func canGroupItem(timelineItem: RoomTimelineItemProtocol, with otherTimelineItem: RoomTimelineItemProtocol) -> Bool { - if timelineItem is CollapsibleTimelineItem || otherTimelineItem is CollapsibleTimelineItem { - return false - } - - guard let eventTimelineItem = timelineItem as? EventBasedTimelineItemProtocol, - let otherEventTimelineItem = otherTimelineItem as? EventBasedTimelineItemProtocol else { - return false + + private func handleRoomInfoUpdate() async { + let pinnedEventIDs = await roomProxy.pinnedEventIDs + // Only update the loading state of the banner + if state.pinnedEventsBannerState.isLoading { + state.pinnedEventsBannerState = .loading(numbersOfEvents: pinnedEventIDs.count) } - // State events aren't rendered as messages so shouldn't be grouped. - if eventTimelineItem is StateRoomTimelineItem || otherEventTimelineItem is StateRoomTimelineItem { - return false + let userID = roomProxy.ownUserID + if case let .success(permission) = await roomProxy.canUserJoinCall(userID: userID) { + state.canJoinCall = permission } - - // can be improved by adding a date threshold - return eventTimelineItem.properties.reactions.isEmpty && eventTimelineItem.sender == otherEventTimelineItem.sender } - - // MARK: - Direct chats logics - - private func showInviteAlert() { - userIndicatorController.alertInfo = .init(id: .init(), - title: L10n.screenRoomInviteAgainAlertTitle, - message: L10n.screenRoomInviteAgainAlertMessage, - primaryButton: .init(title: L10n.actionInvite, action: { [weak self] in self?.inviteOtherDMUserBack() }), - secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) - } - - private let inviteLoadingIndicatorID = UUID().uuidString - - private func inviteOtherDMUserBack() { - guard roomProxy.isUserAloneInDirectRoom else { - userIndicatorController.alertInfo = .init(id: .init(), title: L10n.commonError) + + private func setupPinnedEventsTimelineProviderIfNeeded() { + guard pinnedEventsTimelineProvider == nil else { return } - + Task { - userIndicatorController.submitIndicator(.init(id: inviteLoadingIndicatorID, type: .toast, title: L10n.commonLoading)) - defer { - userIndicatorController.retractIndicatorWithId(inviteLoadingIndicatorID) - } - - guard - let members = await roomProxy.members(), - members.count == 2, - let otherPerson = members.first(where: { $0.userID != roomProxy.ownUserID && $0.membership == .leave }) - else { - userIndicatorController.alertInfo = .init(id: .init(), title: L10n.commonError) + guard let timelineProvider = await roomProxy.pinnedEventsTimeline?.timelineProvider else { return } - - switch await roomProxy.invite(userID: otherPerson.userID) { - case .success: - break - case .failure: - userIndicatorController.alertInfo = .init(id: .init(), - title: L10n.commonUnableToInviteTitle, - message: L10n.commonUnableToInviteMessage) + + if pinnedEventsTimelineProvider == nil { + pinnedEventsTimelineProvider = timelineProvider } } } - - // MARK: - Reactions - - private func displayReactionSummary(for itemID: TimelineItemIdentifier, selectedKey: String) { - guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID), - let eventTimelineItem = timelineItem as? EventBasedTimelineItemProtocol else { - return - } - - state.bindings.reactionSummaryInfo = .init(reactions: eventTimelineItem.properties.reactions, selectedKey: selectedKey) - } - - // MARK: - Read Receipts - - private func displayReadReceipts(for itemID: TimelineItemIdentifier) { - guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID), - let eventTimelineItem = timelineItem as? EventBasedTimelineItemProtocol else { - return - } - - state.bindings.readReceiptsSummaryInfo = .init(orderedReceipts: eventTimelineItem.properties.orderedReadReceipts, id: eventTimelineItem.id) - } - - // MARK: - Message forwarding - - private func forwardMessage(itemID: TimelineItemIdentifier) async { - guard let content = await timelineController.messageEventContent(for: itemID) else { return } - actionsSubject.send(.displayMessageForwarding(forwardingItem: .init(id: itemID, roomID: roomProxy.id, content: content))) - } - - // MARK: - User Indicators - - private func showFocusLoadingIndicator() { - userIndicatorController.submitIndicator(UserIndicator(id: Constants.focusTimelineToastIndicatorID, - type: .toast(progress: .indeterminate), - title: L10n.commonLoading, - persistent: true)) - } - - private func hideFocusLoadingIndicator() { - userIndicatorController.retractIndicatorWithId(Constants.focusTimelineToastIndicatorID) - } - - private func displayAlert(_ type: RoomScreenAlertInfoType) { - switch type { - case .audioRecodingPermissionError: - state.bindings.alertInfo = .init(id: type, - title: L10n.dialogPermissionMicrophoneTitleIos(InfoPlistReader.main.bundleDisplayName), - message: L10n.dialogPermissionMicrophoneDescriptionIos, - primaryButton: .init(title: L10n.commonSettings, action: { [weak self] in self?.appMediator.openAppSettings() }), - secondaryButton: .init(title: L10n.actionNotNow, role: .cancel, action: nil)) - case .pollEndConfirmation(let pollStartID): - state.bindings.alertInfo = .init(id: type, - title: L10n.actionEndPoll, - message: L10n.commonPollEndConfirmation, - primaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil), - secondaryButton: .init(title: L10n.actionOk, action: { self.roomScreenInteractionHandler.endPoll(pollStartID: pollStartID) })) - case .sendingFailed: - state.bindings.alertInfo = .init(id: type, - title: L10n.commonSendingFailed, - primaryButton: .init(title: L10n.actionOk, action: nil)) - case .encryptionAuthenticity(let message): - state.bindings.alertInfo = .init(id: type, - title: message, - primaryButton: .init(title: L10n.actionOk, action: nil)) - } - } - - private func displayErrorToast(_ title: String) { - userIndicatorController.submitIndicator(UserIndicator(id: Constants.toastErrorID, - type: .toast, - title: title, - iconName: "xmark")) - } } -private extension RoomProxyProtocol { - /// Checks if the other person left the room in a direct chat - var isUserAloneInDirectRoom: Bool { - isDirect && activeMembersCount == 1 - } -} - -// MARK: - Mocks - extension RoomScreenViewModel { - static let mock = RoomScreenViewModel(roomProxy: RoomProxyMock(.init(name: "Preview room")), - focussedEventID: nil, - timelineController: MockRoomTimelineController(), - mediaProvider: MockMediaProvider(), - mediaPlayerProvider: MediaPlayerProviderMock(), - voiceMessageMediaManager: VoiceMessageMediaManagerMock(), - userIndicatorController: ServiceLocator.shared.userIndicatorController, - appMediator: AppMediatorMock.default, - appSettings: ServiceLocator.shared.settings, - analyticsService: ServiceLocator.shared.analytics) + static func mock(roomProxyMock: JoinedRoomProxyMock) -> RoomScreenViewModel { + RoomScreenViewModel(roomProxy: roomProxyMock, + initialSelectedPinnedEventID: nil, + mediaProvider: MockMediaProvider(), + ongoingCallRoomIDPublisher: .init(.init(nil)), + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) + } } private struct RoomContextKey: EnvironmentKey { @MainActor static let defaultValue: RoomScreenViewModel.Context? = nil } -private struct FocussedEventID: EnvironmentKey { - static let defaultValue: String? = nil -} - extension EnvironmentValues { /// Used to access and inject the room context without observing it var roomContext: RoomScreenViewModel.Context? { get { self[RoomContextKey.self] } set { self[RoomContextKey.self] = newValue } } - - /// An event ID which will be non-nil when a timeline item should show as focussed. - var focussedEventID: String? { - get { self[FocussedEventID.self] } - set { self[FocussedEventID.self] = newValue } - } } diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModelProtocol.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModelProtocol.swift index 757d36c417..3ab23cb18f 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModelProtocol.swift @@ -1,31 +1,17 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine import Foundation -import SwiftUI -@MainActor protocol RoomScreenViewModelProtocol { var actions: AnyPublisher { get } - var context: RoomScreenViewModelType.Context { get } - func process(composerAction: ComposerToolbarViewModelAction) - /// Updates the timeline to show and highlight the item with the corresponding event ID. - func focusOnEvent(eventID: String) async - func stop() - func loadDraft() - func saveDraft() + var context: RoomScreenViewModel.Context { get } + + func timelineHasScrolled(direction: ScrollDirection) + func setSelectedPinnedEventID(_ eventID: String) } diff --git a/ElementX/Sources/Screens/RoomScreen/View/ItemMenu/TimelineItemMenu.swift b/ElementX/Sources/Screens/RoomScreen/View/ItemMenu/TimelineItemMenu.swift deleted file mode 100644 index 1f007a43a6..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/ItemMenu/TimelineItemMenu.swift +++ /dev/null @@ -1,237 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Compound -import SwiftUI - -struct TimelineItemMenu: View { - @EnvironmentObject private var context: RoomScreenViewModel.Context - @Environment(\.dismiss) private var dismiss - - @State private var reactionsFrame = CGRect.zero - - let item: EventBasedTimelineItemProtocol - let actions: TimelineItemMenuActions - private let feedbackGenerator = UIImpactFeedbackGenerator(style: .heavy) - - var body: some View { - VStack(spacing: 8) { - messagePreview - .frame(idealWidth: 300.0) - - Divider() - .background(Color.compound.bgSubtlePrimary) - - ScrollView { - VStack(alignment: .leading, spacing: 0.0) { - if !actions.reactions.isEmpty { - reactionsSection - .padding(.top, 4.0) - .padding(.bottom, 8.0) - - Divider() - .background(Color.compound.bgSubtlePrimary) - } - - if !actions.actions.isEmpty { - viewsForActions(actions.actions) - - Divider() - .background(Color.compound.bgSubtlePrimary) - } - - viewsForActions(actions.debugActions) - } - } - } - .accessibilityIdentifier(A11yIdentifiers.roomScreen.timelineItemActionMenu) - .presentationDetents([.medium, .large]) - .presentationBackground(Color.compound.bgCanvasDefault) - .presentationDragIndicator(.visible) - } - - private var messagePreview: some View { - VStack(alignment: .leading, spacing: 20) { - HStack(alignment: .top, spacing: 0.0) { - LoadableAvatarImage(url: item.sender.avatarURL, - name: item.sender.displayName, - contentID: item.sender.id, - avatarSize: .user(on: .timeline), - imageProvider: context.imageProvider) - .accessibilityHidden(true) - - Spacer(minLength: 8.0) - - VStack(alignment: .leading, spacing: 0) { - Text(item.sender.displayName ?? item.sender.id) - .font(.compound.bodySMSemibold) - .foregroundColor(.compound.textPrimary) - .textSelection(.enabled) - - Text(item.timelineMenuDescription) - .font(.compound.bodyMD) - .foregroundColor(.compound.textSecondary) - .lineLimit(1) - } - .frame(maxWidth: .infinity, alignment: .leading) - - Spacer(minLength: 16.0) - - Text(item.timestamp) - .font(.compound.bodyXS) - .foregroundColor(.compound.textSecondary) - } - .accessibilityElement(children: .combine) - - if let authenticity = item.properties.encryptionAuthenticity { - Label(authenticity.message, icon: authenticity.icon, iconSize: .small, relativeTo: .compound.bodySMSemibold) - .font(.compound.bodySMSemibold) - .foregroundStyle(authenticity.foregroundStyle) - } - } - .padding(.horizontal) - .padding(.top, 32.0) - .padding(.bottom, 4.0) - } - - 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)) - } - } 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) - } - - private func reactionButton(for emoji: String) -> some View { - Button { - feedbackGenerator.impactOccurred() - dismiss() - context.send(viewAction: .toggleReaction(key: emoji, itemID: item.id)) - } label: { - Text(emoji) - .font(.compound.headingLG) - .padding(8) - .background(Circle() - .foregroundColor(reactionBackgroundColor(for: emoji))) - .frame(maxWidth: .infinity, alignment: .leading) - } - } - - private func reactionBackgroundColor(for emoji: String) -> Color { - if let reaction = item.properties.reactions.first(where: { $0.key == emoji }), - reaction.isHighlighted { - return .compound.bgActionPrimaryRest - } else { - return .clear - } - } - - private func viewsForActions(_ actions: [TimelineItemMenuAction]) -> some View { - ForEach(actions, id: \.self) { action in - Button(role: action.isDestructive ? .destructive : nil) { - send(action) - } label: { - action.label - .labelStyle(.menuSheet) - } - } - } - - private func send(_ action: TimelineItemMenuAction) { - dismiss() - // Otherwise we might get errors that a sheet is already presented - DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { - context.send(viewAction: .handleTimelineItemMenuAction(itemID: item.id, action: action)) - } - } -} - -private extension EncryptionAuthenticity { - var foregroundStyle: SwiftUI.Color { - switch color { - case .red: .compound.textCriticalPrimary - case .gray: .compound.textSecondary - } - } -} - -// MARK: - Previews - -struct TimelineItemMenu_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.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 var previews: some View { - TimelineItemMenu(item: item, actions: actions) - .environmentObject(viewModel.context) - .previewDisplayName("With button shapes off") - - TimelineItemMenu(item: item, actions: actions) - .environmentObject(viewModel.context) - .environment(\._accessibilityShowButtonShapes, true) - .previewDisplayName("With button shapes on") - - TimelineItemMenu(item: backupItem, actions: actions) - .environmentObject(viewModel.context) - .previewDisplayName("Authenticity not guaranteed") - - TimelineItemMenu(item: unsignedItem, actions: actions) - .environmentObject(viewModel.context) - .previewDisplayName("Unsigned") - - TimelineItemMenu(item: unencryptedItem, actions: actions) - .environmentObject(viewModel.context) - .previewDisplayName("Unencrypted") - } - - static func makeItem(authenticity: EncryptionAuthenticity? = 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]) else { - return nil - } - - if let authenticity { - item.properties.encryptionAuthenticity = authenticity - } - - return (item, actions) - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/PinnedItemsBanner/PinnedItemsBannerView.swift b/ElementX/Sources/Screens/RoomScreen/View/PinnedItemsBanner/PinnedItemsBannerView.swift index 8cb77c8b0f..83b58d207d 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/PinnedItemsBanner/PinnedItemsBannerView.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/PinnedItemsBanner/PinnedItemsBannerView.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -38,7 +29,7 @@ struct PinnedItemsBannerView: View { Button { onMainButtonTap() } label: { HStack(spacing: 0) { HStack(spacing: 10) { - PinnedItemsIndicatorView(pinIndex: state.selectedPinIndex, pinsCount: state.count) + PinnedItemsIndicatorView(pinIndex: state.selectedPinnedIndex, pinsCount: state.count) .accessibilityHidden(true) CompoundIcon(\.pinSolid, size: .small, relativeTo: .compound.bodyMD) .foregroundColor(Color.compound.iconSecondaryAlpha) @@ -54,27 +45,31 @@ struct PinnedItemsBannerView: View { @ViewBuilder private var viewAllButton: some View { - switch state { - case .loaded: - Button { onViewAllButtonTap() } label: { - Text(L10n.screenRoomPinnedBannerViewAllButtonTitle) - .font(.compound.bodyMDSemibold) - .foregroundStyle(Color.compound.textPrimary) - .padding(.horizontal, 16) - .padding(.vertical, 5) - } - case .loading: - ProgressView() + Button { onViewAllButtonTap() } label: { + Text(state.isLoading ? "" : L10n.screenRoomPinnedBannerViewAllButtonTitle) + .font(.compound.bodyMDSemibold) + .foregroundStyle(Color.compound.textPrimary) + .opacity(state.isLoading ? 0 : 1) + // Use overlay instead otherwise the sliding animation would not work + .overlay(alignment: .trailing) { + ProgressView() + .opacity(state.isLoading ? 1 : 0) + } .padding(.horizontal, 16) + .padding(.vertical, 5) } + .disabled(state.isLoading) } private var content: some View { VStack(alignment: .leading, spacing: 0) { - Text(state.bannerIndicatorDescription) - .font(.compound.bodySM) - .foregroundColor(.compound.textActionAccent) - .lineLimit(1) + // Only the display the indicator description for more than 1 pinned item + if state.count > 1 { + Text(state.bannerIndicatorDescription) + .font(.compound.bodySM) + .foregroundColor(.compound.textActionAccent) + .lineLimit(1) + } Text(state.displayedMessage) .font(.compound.bodyMD) .foregroundColor(.compound.textPrimary) @@ -98,16 +93,16 @@ struct PinnedItemsBannerView_Previews: PreviewProvider, TestablePreview { PinnedItemsBannerView(state: .loaded(state: .init(pinnedEventContents: ["1": "Content", "2": "2", "3": "3"], - selectedPinEventID: "1")), + selectedPinnedEventID: "1")), onMainButtonTap: { }, onViewAllButtonTap: { }) PinnedItemsBannerView(state: .loaded(state: .init(pinnedEventContents: ["1": "Very very very very long content here", "2": "2"], - selectedPinEventID: "1")), + selectedPinnedEventID: "1")), onMainButtonTap: { }, onViewAllButtonTap: { }) PinnedItemsBannerView(state: .loaded(state: .init(pinnedEventContents: ["1": attributedContent], - selectedPinEventID: "1")), + selectedPinnedEventID: "1")), onMainButtonTap: { }, onViewAllButtonTap: { }) PinnedItemsBannerView(state: .loading(numbersOfEvents: 5), diff --git a/ElementX/Sources/Screens/RoomScreen/View/PinnedItemsBanner/PinnedItemsIndicatorView.swift b/ElementX/Sources/Screens/RoomScreen/View/PinnedItemsBanner/PinnedItemsIndicatorView.swift index bc11192ca7..934399d046 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/PinnedItemsBanner/PinnedItemsIndicatorView.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/PinnedItemsBanner/PinnedItemsIndicatorView.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/RoomScreen/View/Polls/PollView.swift b/ElementX/Sources/Screens/RoomScreen/View/Polls/PollView.swift deleted file mode 100644 index 7bd44641c0..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Polls/PollView.swift +++ /dev/null @@ -1,173 +0,0 @@ -// -// Copyright 2023 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Compound -import SwiftUI - -enum PollViewAction { - case selectOption(optionID: String) - case edit - case end -} - -struct PollView: View { - private let feedbackGenerator = UIImpactFeedbackGenerator(style: .heavy) - - let poll: Poll - let editable: Bool - let actionHandler: (PollViewAction) -> Void - - var body: some View { - VStack(alignment: .leading, spacing: 16) { - questionView - optionsView - summaryView - toolbarView - } - .frame(maxWidth: 450) - } - - // MARK: - Private - - private var questionView: some View { - HStack(alignment: .top, spacing: 12) { - CompoundIcon(poll.hasEnded ? \.pollsEnd : \.polls, - size: .custom(22), - relativeTo: .compound.bodyLGSemibold) - .accessibilityHidden(true) - - Text(poll.question) - .multilineTextAlignment(.leading) - .font(.compound.bodyLGSemibold) - } - } - - private var optionsView: some View { - ForEach(poll.options, id: \.id) { option in - Button { - guard !option.isSelected else { return } - actionHandler(.selectOption(optionID: option.id)) - feedbackGenerator.impactOccurred() - } label: { - PollOptionView(pollOption: option, - showVotes: showVotes, - isFinalResult: poll.hasEnded) - .foregroundColor(progressBarColor(for: option)) - } - .disabled(poll.hasEnded) - } - } - - @ViewBuilder - private var summaryView: some View { - if let summaryText = poll.summaryText { - Text(summaryText) - .font(.compound.bodySM) - .scaledPadding(.leading, showVotes ? 0 : 32) - .foregroundColor(.compound.textSecondary) - .frame(maxWidth: .infinity, alignment: showVotes ? .trailing : .leading) - } - } - - @ViewBuilder - private var toolbarView: some View { - if !poll.hasEnded, poll.createdByAccountOwner { - Button { - toolbarAction() - } label: { - Text(editable ? L10n.actionEditPoll : L10n.actionEndPoll) - .lineLimit(2, reservesSpace: false) - .font(.compound.bodyLGSemibold) - .foregroundColor(.compound.textOnSolidPrimary) - .padding(.horizontal, 24) - .padding(.vertical, 10) - .frame(maxWidth: .infinity) - .background { - Capsule() - .foregroundColor(.compound.bgActionPrimaryRest) - } - } - .padding(.top, 8) - } - } - - private func toolbarAction() { - if editable { - actionHandler(.edit) - } else { - actionHandler(.end) - } - } - - private func progressBarColor(for option: Poll.Option) -> Color { - if poll.hasEnded { - return option.isWinning ? .compound.textActionAccent : .compound.textDisabled - } else { - return .compound.textPrimary - } - } - - private var showVotes: Bool { - poll.hasEnded || poll.kind == .disclosed - } -} - -private extension Poll { - var summaryText: String? { - guard !hasEnded else { - return options.first.map { - L10n.commonPollTotalVotes($0.allVotes) - } - } - - switch kind { - case .disclosed: - return options.first.map { - L10n.commonPollTotalVotes($0.allVotes) - } - case .undisclosed: - return L10n.commonPollUndisclosedText - } - } -} - -struct PollView_Previews: PreviewProvider, TestablePreview { - static var previews: some View { - PollView(poll: .disclosed(), editable: false) { _ in } - .padding() - .previewDisplayName("Disclosed") - - PollView(poll: .undisclosed(), editable: false) { _ in } - .padding() - .previewDisplayName("Undisclosed") - - PollView(poll: .endedDisclosed, editable: false) { _ in } - .padding() - .previewDisplayName("Ended, Disclosed") - - PollView(poll: .endedUndisclosed, editable: false) { _ in } - .padding() - .previewDisplayName("Ended, Undisclosed") - - PollView(poll: .disclosed(createdByAccountOwner: true), editable: true) { _ in } - .padding() - .previewDisplayName("Creator, disclosed") - - PollView(poll: .emptyDisclosed, editable: true) { _ in } - .padding() - .previewDisplayName("Creator, no votes") - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/ReadReceipts/ReadReceiptsSummaryView.swift b/ElementX/Sources/Screens/RoomScreen/View/ReadReceipts/ReadReceiptsSummaryView.swift deleted file mode 100644 index 165c8aae93..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/ReadReceipts/ReadReceiptsSummaryView.swift +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright 2023 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import SwiftUI - -struct ReadReceiptsSummaryView: View { - let orderedReadReceipts: [ReadReceipt] - @EnvironmentObject private var context: RoomScreenViewModel.Context - - var body: some View { - VStack(alignment: .leading, spacing: 16) { - Text(L10n.commonSeenBy) - .font(.compound.bodyLGSemibold) - .foregroundColor(.compound.textPrimary) - .padding(.horizontal, 16) - ScrollView { - LazyVStack(spacing: 0) { - ForEach(orderedReadReceipts) { receipt in - ReadReceiptCell(readReceipt: receipt, - memberState: context.viewState.members[receipt.userID], - imageProvider: context.imageProvider) - } - } - } - } - .padding(.top, 24) - .presentationDetents([.medium, .large]) - .presentationBackground(Color.compound.bgCanvasDefault) - .presentationDragIndicator(.visible) - } -} - -struct ReadReceiptsSummaryView_Previews: PreviewProvider, TestablePreview { - static let viewModel = { - let members: [RoomMemberProxyMock] = [ - .mockAlice, - .mockBob, - .mockCharlie, - .mockDan - ] - let roomProxyMock = RoomProxyMock(.init(name: "Room", members: members)) - let mock = RoomScreenViewModel(roomProxy: roomProxyMock, - timelineController: MockRoomTimelineController(), - mediaProvider: MockMediaProvider(), - mediaPlayerProvider: MediaPlayerProviderMock(), - voiceMessageMediaManager: VoiceMessageMediaManagerMock(), - userIndicatorController: UserIndicatorControllerMock(), - appMediator: AppMediatorMock.default, - appSettings: ServiceLocator.shared.settings, - analyticsService: ServiceLocator.shared.analytics) - return mock - }() - - static let orderedReadReceipts: [ReadReceipt] = [ - .init(userID: "@alice:matrix.org", formattedTimestamp: "10:00"), - .init(userID: "@bob:matrix.org", formattedTimestamp: "9:30"), - .init(userID: "@charlie:matrix.org", formattedTimestamp: "9:00"), - .init(userID: "@dan:matrix.org", formattedTimestamp: "8:30"), - .init(userID: "@loading:matrix.org", formattedTimestamp: "Long time ago") - ] - - static var previews: some View { - ReadReceiptsSummaryView(orderedReadReceipts: orderedReadReceipts) - .environmentObject(viewModel.context) - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/RoomHeaderView.swift b/ElementX/Sources/Screens/RoomScreen/View/RoomHeaderView.swift index e0cc306f4b..e138e2fac6 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/RoomHeaderView.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/RoomHeaderView.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -22,13 +13,14 @@ struct RoomHeaderView: View { let roomName: String let roomAvatar: RoomAvatar - let imageProvider: ImageProviderProtocol? + let mediaProvider: MediaProviderProtocol? var body: some View { HStack(spacing: 12) { avatarImage .accessibilityHidden(true) Text(roomName) + .lineLimit(1) .font(.compound.bodyLGSemibold) .accessibilityIdentifier(A11yIdentifiers.roomScreen.name) } @@ -39,7 +31,7 @@ struct RoomHeaderView: View { private var avatarImage: some View { RoomAvatarImage(avatar: roomAvatar, avatarSize: .room(on: .timeline), - imageProvider: imageProvider) + mediaProvider: mediaProvider) .accessibilityIdentifier(A11yIdentifiers.roomScreen.avatar) } } @@ -50,7 +42,7 @@ struct RoomHeaderView_Previews: PreviewProvider, TestablePreview { roomAvatar: .room(id: "1", name: "Some Room Name", avatarURL: URL.picturesDirectory), - imageProvider: MockMediaProvider()) + mediaProvider: MockMediaProvider()) .previewLayout(.sizeThatFits) .padding() @@ -58,7 +50,7 @@ struct RoomHeaderView_Previews: PreviewProvider, TestablePreview { roomAvatar: .room(id: "1", name: "Some Room Name", avatarURL: nil), - imageProvider: MockMediaProvider()) + mediaProvider: MockMediaProvider()) .previewLayout(.sizeThatFits) .padding() } diff --git a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift index 0655395a9e..e1f1b81ea0 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -19,13 +10,17 @@ import SwiftUI import WysiwygComposer struct RoomScreen: View { - @ObservedObject var context: RoomScreenViewModel.Context + @ObservedObject var roomContext: RoomScreenViewModel.Context + @ObservedObject var timelineContext: TimelineViewModel.Context @ObservedObject private var composerToolbarContext: ComposerToolbarViewModel.Context @State private var dragOver = false let composerToolbar: ComposerToolbar - init(context: RoomScreenViewModel.Context, composerToolbar: ComposerToolbar) { - self.context = context + init(roomViewModel: RoomScreenViewModelProtocol, + timelineViewModel: TimelineViewModelProtocol, + composerToolbar: ComposerToolbar) { + roomContext = roomViewModel.context + timelineContext = timelineViewModel.context self.composerToolbar = composerToolbar composerToolbarContext = composerToolbar.context } @@ -45,16 +40,16 @@ struct RoomScreen: View { } .padding(.top, 8) .background(Color.compound.bgCanvasDefault.ignoresSafeArea()) - .environmentObject(context) - .environment(\.roomContext, context) + .environmentObject(timelineContext) + .environment(\.timelineContext, timelineContext) } .overlay(alignment: .top) { Group { - if context.viewState.shouldShowPinnedEventsBanner { + if roomContext.viewState.shouldShowPinnedEventsBanner { pinnedItemsBanner } } - .animation(.elementDefault, value: context.viewState.shouldShowPinnedEventsBanner) + .animation(.elementDefault, value: roomContext.viewState.shouldShowPinnedEventsBanner) } .navigationTitle(L10n.screenRoomTitle) // Hidden but used for back button text. .navigationBarTitleDisplayMode(.inline) @@ -62,30 +57,35 @@ struct RoomScreen: View { .toolbar { toolbar } .toolbarBackground(.visible, for: .navigationBar) // Fix the toolbar's background. .overlay { loadingIndicator } - .alert(item: $context.alertInfo) - .sheet(item: $context.debugInfo) { TimelineItemDebugView(info: $0) } - .sheet(item: $context.actionMenuInfo) { info in + .alert(item: $timelineContext.alertInfo) + .sheet(item: $timelineContext.debugInfo) { TimelineItemDebugView(info: $0) } + .sheet(item: $timelineContext.actionMenuInfo) { info in let actions = TimelineItemMenuActionProvider(timelineItem: info.item, - canCurrentUserRedactSelf: context.viewState.canCurrentUserRedactSelf, - canCurrentUserRedactOthers: context.viewState.canCurrentUserRedactOthers, - canCurrentUserPin: context.viewState.canCurrentUserPin, - pinnedEventIDs: context.viewState.pinnedEventIDs, - isDM: context.viewState.isEncryptedOneToOneRoom, - isViewSourceEnabled: context.viewState.isViewSourceEnabled).makeActions() + canCurrentUserRedactSelf: timelineContext.viewState.canCurrentUserRedactSelf, + canCurrentUserRedactOthers: timelineContext.viewState.canCurrentUserRedactOthers, + canCurrentUserPin: timelineContext.viewState.canCurrentUserPin, + pinnedEventIDs: timelineContext.viewState.pinnedEventIDs, + isDM: timelineContext.viewState.isEncryptedOneToOneRoom, + isViewSourceEnabled: timelineContext.viewState.isViewSourceEnabled, + isPinnedEventsTimeline: timelineContext.viewState.isPinnedEventsTimeline) + .makeActions() if let actions { TimelineItemMenu(item: info.item, actions: actions) - .environmentObject(context) + .environmentObject(timelineContext) } } - .sheet(item: $context.reactionSummaryInfo) { - ReactionsSummaryView(reactions: $0.reactions, members: context.viewState.members, imageProvider: context.imageProvider, selectedReactionKey: $0.selectedKey) + .sheet(item: $timelineContext.reactionSummaryInfo) { + ReactionsSummaryView(reactions: $0.reactions, + members: timelineContext.viewState.members, + mediaProvider: timelineContext.mediaProvider, + selectedReactionKey: $0.selectedKey) .edgesIgnoringSafeArea([.bottom]) } - .sheet(item: $context.readReceiptsSummaryInfo) { + .sheet(item: $timelineContext.readReceiptsSummaryInfo) { ReadReceiptsSummaryView(orderedReadReceipts: $0.orderedReceipts) - .environmentObject(context) + .environmentObject(timelineContext) } - .interactiveQuickLook(item: $context.mediaPreviewItem) + .interactiveQuickLook(item: $timelineContext.mediaPreviewItem) .track(screen: .Room) .onDrop(of: ["public.item", "public.file-url"], isTargeted: $dragOver) { providers -> Bool in guard let provider = providers.first, @@ -93,7 +93,7 @@ struct RoomScreen: View { return false } - context.send(viewAction: .handlePasteOrDrop(provider: provider)) + timelineContext.send(viewAction: .handlePasteOrDrop(provider: provider)) return true } .sentryTrace("\(Self.self)") @@ -101,23 +101,23 @@ struct RoomScreen: View { private var timeline: some View { TimelineView() - .id(context.viewState.roomID) - .environmentObject(context) - .environment(\.focussedEventID, context.viewState.timelineViewState.focussedEvent?.eventID) + .id(timelineContext.viewState.roomID) + .environmentObject(timelineContext) + .environment(\.focussedEventID, timelineContext.viewState.timelineViewState.focussedEvent?.eventID) .overlay(alignment: .bottomTrailing) { scrollToBottomButton } } private var pinnedItemsBanner: some View { - PinnedItemsBannerView(state: context.viewState.pinnedEventsBannerState, - onMainButtonTap: { context.send(viewAction: .tappedPinnedEventsBanner) }, - onViewAllButtonTap: { context.send(viewAction: .viewAllPins) }) + PinnedItemsBannerView(state: roomContext.viewState.pinnedEventsBannerState, + onMainButtonTap: { roomContext.send(viewAction: .tappedPinnedEventsBanner) }, + onViewAllButtonTap: { roomContext.send(viewAction: .viewAllPins) }) .transition(.move(edge: .top)) } private var scrollToBottomButton: some View { - Button { context.send(viewAction: .scrollToBottom) } label: { + Button { timelineContext.send(viewAction: .scrollToBottom) } label: { Image(systemName: "chevron.down") .font(.compound.bodyLG) .fontWeight(.semibold) @@ -139,12 +139,12 @@ struct RoomScreen: View { } private var isAtBottomAndLive: Bool { - context.isScrolledToBottom && context.viewState.timelineViewState.isLive + timelineContext.isScrolledToBottom && timelineContext.viewState.timelineViewState.isLive } @ViewBuilder private var loadingIndicator: some View { - if context.viewState.showLoading { + if timelineContext.viewState.showLoading { ProgressView() .progressViewStyle(.circular) .tint(.compound.textPrimary) @@ -159,29 +159,31 @@ struct RoomScreen: View { // .principal + .primaryAction works better than .navigation leading + trailing // as the latter disables interaction in the action button for rooms with long names ToolbarItem(placement: .principal) { - RoomHeaderView(roomName: context.viewState.roomTitle, - roomAvatar: context.viewState.roomAvatar, - imageProvider: context.imageProvider) + RoomHeaderView(roomName: roomContext.viewState.roomTitle, + roomAvatar: roomContext.viewState.roomAvatar, + mediaProvider: roomContext.mediaProvider) // Using a button stops it from getting truncated in the navigation bar .contentShape(.rect) .onTapGesture { - context.send(viewAction: .displayRoomDetails) + roomContext.send(viewAction: .displayRoomDetails) } } if !ProcessInfo.processInfo.isiOSAppOnMac { ToolbarItem(placement: .primaryAction) { - callButton - .disabled(context.viewState.canJoinCall == false) + if roomContext.viewState.shouldShowCallButton { + callButton + .disabled(!roomContext.viewState.canJoinCall) + } } } } @ViewBuilder private var callButton: some View { - if context.viewState.hasOngoingCall { + if roomContext.viewState.hasOngoingCall { Button { - context.send(viewAction: .displayCall) + roomContext.send(viewAction: .displayCall) } label: { Label(L10n.actionJoin, icon: \.videoCallSolid) .labelStyle(.titleAndIcon) @@ -190,7 +192,7 @@ struct RoomScreen: View { .accessibilityIdentifier(A11yIdentifiers.roomScreen.joinCall) } else { Button { - context.send(viewAction: .displayCall) + roomContext.send(viewAction: .displayCall) } label: { CompoundIcon(\.videoCallSolid) } @@ -206,21 +208,25 @@ struct RoomScreen: View { // MARK: - Previews struct RoomScreen_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel(roomProxy: RoomProxyMock(.init(id: "stable_id", - name: "Preview room", - hasOngoingCall: true)), - timelineController: MockRoomTimelineController(), - mediaProvider: MockMediaProvider(), - mediaPlayerProvider: MediaPlayerProviderMock(), - voiceMessageMediaManager: VoiceMessageMediaManagerMock(), - userIndicatorController: ServiceLocator.shared.userIndicatorController, - appMediator: AppMediatorMock.default, - appSettings: ServiceLocator.shared.settings, - analyticsService: ServiceLocator.shared.analytics) + static let roomProxyMock = JoinedRoomProxyMock(.init(id: "stable_id", + name: "Preview room", + hasOngoingCall: true)) + static let roomViewModel = RoomScreenViewModel.mock(roomProxyMock: roomProxyMock) + static let timelineViewModel = TimelineViewModel(roomProxy: roomProxyMock, + timelineController: MockRoomTimelineController(), + mediaProvider: MockMediaProvider(), + mediaPlayerProvider: MediaPlayerProviderMock(), + voiceMessageMediaManager: VoiceMessageMediaManagerMock(), + userIndicatorController: ServiceLocator.shared.userIndicatorController, + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) static var previews: some View { NavigationStack { - RoomScreen(context: viewModel.context, composerToolbar: ComposerToolbar.mock()) + RoomScreen(roomViewModel: roomViewModel, + timelineViewModel: timelineViewModel, + composerToolbar: ComposerToolbar.mock()) } } } diff --git a/ElementX/Sources/Screens/RoomScreen/View/Style/SwipeToReplyView.swift b/ElementX/Sources/Screens/RoomScreen/View/Style/SwipeToReplyView.swift deleted file mode 100644 index 0c5a2d7fc5..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Style/SwipeToReplyView.swift +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright 2023 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Compound -import SwiftUI - -struct SwipeToReplyView: View { - let timelineItem: RoomTimelineItemProtocol - - var body: some View { - CompoundIcon(\.reply) - .foregroundColor(.compound.iconPrimary) - .accessibilityHidden(true) - } -} - -struct SwipeToReplyView_Previews: PreviewProvider, TestablePreview { - static let timelineItem = TextRoomTimelineItem(id: .init(timelineID: ""), - timestamp: "", - isOutgoing: true, - isEditable: true, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: ""), - content: .init(body: "")) - - static var previews: some View { - SwipeToReplyView(timelineItem: timelineItem) - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Style/ThreadDecorator.swift b/ElementX/Sources/Screens/RoomScreen/View/Style/ThreadDecorator.swift deleted file mode 100644 index 632a5f64b4..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Style/ThreadDecorator.swift +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright 2023 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import SwiftUI - -import Compound - -struct ThreadDecorator: View { - var body: some View { - Label { - Text(L10n.commonThread) - .foregroundColor(.compound.textPrimary) - .font(.compound.bodyXS) - } icon: { - CompoundIcon(\.threads, size: .xSmall, relativeTo: .compound.bodyXS) - .foregroundColor(.compound.iconSecondary) - } - .labelStyle(.custom(spacing: 4)) - } -} - -struct ThreadDecorator_Previews: PreviewProvider, TestablePreview { - static var previews: some View { - ThreadDecorator() - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Style/TimelineItemAccessibilityModifier.swift b/ElementX/Sources/Screens/RoomScreen/View/Style/TimelineItemAccessibilityModifier.swift deleted file mode 100644 index cb35adf494..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Style/TimelineItemAccessibilityModifier.swift +++ /dev/null @@ -1,58 +0,0 @@ -// -// Copyright 2023 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import SwiftUI - -private struct TimelineItemAccessibilityModifier: ViewModifier { - let timelineItem: RoomTimelineItemProtocol - let action: () -> Void - - @ViewBuilder - func body(content: Content) -> some View { - switch timelineItem { - case is PollRoomTimelineItem, is VoiceMessageRoomTimelineItem: - content - .accessibilityActions { - Button(L10n.commonMessageActions) { - action() - } - } - case let timelineItem as EventBasedTimelineItemProtocol: - content - .accessibilityRepresentation { - VStack(spacing: 8) { - Text(timelineItem.sender.displayName ?? timelineItem.sender.id) - content - } - } - .accessibilityElement(children: .combine) - .accessibilityActions { - Button(L10n.commonMessageActions) { - action() - } - } - default: - content - .accessibilityElement(children: .combine) - } - } -} - -extension View { - func timelineItemAccessibility(_ timelineItem: RoomTimelineItemProtocol, action: @escaping () -> Void) -> some View { - modifier(TimelineItemAccessibilityModifier(timelineItem: timelineItem, action: action)) - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Style/TimelineItemBubbledStylerView.swift b/ElementX/Sources/Screens/RoomScreen/View/Style/TimelineItemBubbledStylerView.swift deleted file mode 100644 index 0883697852..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Style/TimelineItemBubbledStylerView.swift +++ /dev/null @@ -1,558 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Compound -import SwiftUI - -struct TimelineItemBubbledStylerView: View { - @EnvironmentObject private var context: RoomScreenViewModel.Context - @Environment(\.timelineGroupStyle) private var timelineGroupStyle - @Environment(\.focussedEventID) private var focussedEventID - - let timelineItem: EventBasedTimelineItemProtocol - let adjustedDeliveryStatus: TimelineItemDeliveryStatus? - @ViewBuilder let content: () -> Content - - private var isEncryptedOneToOneRoom: Bool { context.viewState.isEncryptedOneToOneRoom } - private var isFocussed: Bool { focussedEventID != nil && timelineItem.id.eventID == focussedEventID } - - /// The base padding applied to bubbles on either side. - /// - /// **Note:** This is on top of the insets applied to the cells by the table view. - private let bubbleHorizontalPadding: CGFloat = 8 - /// Additional padding applied to outgoing bubbles when the avatar is shown - private var bubbleAvatarPadding: CGFloat { - guard !timelineItem.isOutgoing, !isEncryptedOneToOneRoom else { return 0 } - return 8 - } - - var body: some View { - ZStack(alignment: .trailingFirstTextBaseline) { - VStack(alignment: alignment, spacing: -12) { - if !timelineItem.isOutgoing, !isEncryptedOneToOneRoom { - header - .zIndex(1) - } - - VStack(alignment: alignment, spacing: 0) { - HStack(spacing: 0) { - if timelineItem.isOutgoing { - Spacer() - } - - messageBubbleWithReactions - } - .padding(timelineItem.isOutgoing ? .leading : .trailing, 48) // Additional padding to differentiate alignment. - - HStack(spacing: 0) { - if !timelineItem.isOutgoing { - Spacer() - } - TimelineItemStatusView(timelineItem: timelineItem, adjustedDeliveryStatus: adjustedDeliveryStatus) - .environmentObject(context) - .padding(.top, 8) - .padding(.bottom, 3) - } - } - .padding(.horizontal, bubbleHorizontalPadding) - .padding(.leading, bubbleAvatarPadding) - } - } - .padding(EdgeInsets(top: 1, leading: 8, bottom: 1, trailing: 8)) - .highlightedTimelineItem(isFocussed) - } - - @ViewBuilder - private var header: some View { - if shouldShowSenderDetails { - HStack(alignment: .top, spacing: 4) { - TimelineSenderAvatarView(timelineItem: timelineItem) - HStack(alignment: .center, spacing: 4) { - Text(timelineItem.sender.displayName ?? timelineItem.sender.id) - .font(.compound.bodySMSemibold) - .foregroundColor(.compound.decorativeColor(for: timelineItem.sender.id).text) - - if timelineItem.sender.displayName != nil, timelineItem.sender.isDisplayNameAmbiguous { - Text(timelineItem.sender.id) - .font(.compound.bodyXS) - .foregroundColor(.compound.textSecondary) - } - } - .lineLimit(1) - .scaledPadding(.vertical, 3) - } - // sender info are read inside the `TimelineAccessibilityModifier` - .accessibilityHidden(true) - .onTapGesture { - context.send(viewAction: .displayRoomMemberDetails(userID: timelineItem.sender.id)) - } - .padding(.top, 8) - } - } - - private var messageBubbleWithReactions: some View { - // Figma overlaps reactions by 3 - VStack(alignment: alignment, spacing: -3) { - messageBubbleWithActions - .timelineItemAccessibility(timelineItem) { - context.send(viewAction: .displayTimelineItemMenu(itemID: timelineItem.id)) - } - - if !timelineItem.properties.reactions.isEmpty { - TimelineReactionsView(context: context, - itemID: timelineItem.id, - reactions: timelineItem.properties.reactions, - isLayoutRTL: timelineItem.isOutgoing) - // Workaround to stop the message long press stealing the touch from the reaction buttons - .onTapGesture { } - } - } - } - - 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)) - } - .swipeRightAction { - SwipeToReplyView(timelineItem: timelineItem) - } shouldStartAction: { - timelineItem.canBeRepliedTo - } action: { - let isThread = (timelineItem as? EventBasedMessageTimelineItemProtocol)?.isThreaded ?? false - context.send(viewAction: .handleTimelineItemMenuAction(itemID: timelineItem.id, action: .reply(isThread: isThread))) - } - .contextMenu { - let provider = TimelineItemMenuActionProvider(timelineItem: timelineItem, - canCurrentUserRedactSelf: context.viewState.canCurrentUserRedactSelf, - canCurrentUserRedactOthers: context.viewState.canCurrentUserRedactOthers, - canCurrentUserPin: context.viewState.canCurrentUserPin, - pinnedEventIDs: context.viewState.pinnedEventIDs, - isDM: context.viewState.isEncryptedOneToOneRoom, - isViewSourceEnabled: context.viewState.isViewSourceEnabled) - TimelineItemMacContextMenu(item: timelineItem, actionProvider: provider) { action in - context.send(viewAction: .handleTimelineItemMenuAction(itemID: timelineItem.id, action: action)) - } - } - .padding(.top, messageBubbleTopPadding) - } - - var messageBubble: some View { - contentWithReply - .timelineItemSendInfo(timelineItem: timelineItem, adjustedDeliveryStatus: adjustedDeliveryStatus, context: context) - .bubbleStyle(insets: timelineItem.bubbleInsets, - color: timelineItem.bubbleBackgroundColor, - corners: roundedCorners) - } - - @ViewBuilder - var contentWithReply: some View { - TimelineBubbleLayout(spacing: 8) { - if let messageTimelineItem = timelineItem as? EventBasedMessageTimelineItemProtocol { - if messageTimelineItem.isThreaded { - ThreadDecorator() - .padding(.leading, 4) - .layoutPriority(TimelineBubbleLayout.Priority.regularText) - } - - if let replyDetails = messageTimelineItem.replyDetails { - // The rendered reply bubble with a greedy width. The custom layout prevents - // the infinite width from increasing the overall width of the view. - - TimelineReplyView(placement: .timeline, timelineItemReplyDetails: replyDetails) - .fixedSize(horizontal: false, vertical: true) - .padding(4.0) - .frame(maxWidth: .infinity, alignment: .leading) - .background(Color.compound.bgCanvasDefault) - .cornerRadius(8) - .layoutPriority(TimelineBubbleLayout.Priority.visibleQuote) - .onTapGesture { - context.send(viewAction: .focusOnEventID(replyDetails.eventID)) - } - - // Add a fixed width reply bubble that is used for layout calculations but won't be rendered. - TimelineReplyView(placement: .timeline, timelineItemReplyDetails: replyDetails) - .fixedSize(horizontal: false, vertical: true) - .padding(4.0) - .layoutPriority(TimelineBubbleLayout.Priority.hiddenQuote) - .hidden() - } - } - - content() - .layoutPriority(TimelineBubbleLayout.Priority.regularText) - .cornerRadius(timelineItem.contentCornerRadius) - } - } - - private var messageBubbleTopPadding: CGFloat { - guard timelineItem.isOutgoing || isEncryptedOneToOneRoom else { return 0 } - return timelineGroupStyle == .single || timelineGroupStyle == .first ? 8 : 0 - } - - private var alignment: HorizontalAlignment { - timelineItem.isOutgoing ? .trailing : .leading - } - - private var roundedCorners: UIRectCorner { - switch timelineGroupStyle { - case .single: - return .allCorners - case .first: - if timelineItem.isOutgoing { - return [.topLeft, .topRight, .bottomLeft] - } else { - return [.topLeft, .topRight, .bottomRight] - } - case .middle: - return timelineItem.isOutgoing ? [.topLeft, .bottomLeft] : [.topRight, .bottomRight] - case .last: - if timelineItem.isOutgoing { - return [.topLeft, .bottomLeft, .bottomRight] - } else { - return [.topRight, .bottomLeft, .bottomRight] - } - } - } - - private var shouldShowSenderDetails: Bool { - timelineGroupStyle.shouldShowSenderDetails - } -} - -private extension View { - func bubbleStyle(insets: EdgeInsets, color: Color? = nil, cornerRadius: CGFloat = 12, corners: UIRectCorner) -> some View { - padding(insets) - .background(color) - .cornerRadius(cornerRadius, corners: corners) - } -} - -private extension EventBasedTimelineItemProtocol { - var bubbleBackgroundColor: Color? { - let defaultColor: Color = isOutgoing ? .compound._bgBubbleOutgoing : .compound._bgBubbleIncoming - - switch self { - case let self as EventBasedMessageTimelineItemProtocol: - switch self { - case is ImageRoomTimelineItem, is VideoRoomTimelineItem: - // In case a reply detail or a thread decorator is present we render the color and the padding - return self.replyDetails != nil || self.isThreaded ? defaultColor : nil - default: - return defaultColor - } - case is StickerRoomTimelineItem: - return nil - default: - return defaultColor - } - } - - /// The insets for the full bubble content. - /// Padding affecting just the "send info" should be added inside `TimelineItemSendInfoView` - var bubbleInsets: EdgeInsets { - let defaultInsets: EdgeInsets = .init(around: 8) - - switch self { - case is StickerRoomTimelineItem: - return .zero - case is PollRoomTimelineItem: - return .init(top: 12, leading: 12, bottom: 4, trailing: 12) - case let self as EventBasedMessageTimelineItemProtocol: - switch self { - // In case a reply detail or a thread decorator is present we render the color and the padding - case is ImageRoomTimelineItem, - is VideoRoomTimelineItem: - return self.replyDetails != nil || - self.isThreaded ? defaultInsets : .zero - case let locationTimelineItem as LocationRoomTimelineItem: - return locationTimelineItem.content.geoURI == nil || - self.replyDetails != nil || - self.isThreaded ? defaultInsets : .zero - default: - return defaultInsets - } - default: - return defaultInsets - } - } - - var contentCornerRadius: CGFloat { - guard let message = self as? EventBasedMessageTimelineItemProtocol else { return .zero } - - switch message { - case is ImageRoomTimelineItem, is VideoRoomTimelineItem, is LocationRoomTimelineItem: - return message.replyDetails != nil || message.isThreaded ? 8 : .zero - default: - return .zero - } - } -} - -private extension EdgeInsets { - init(around: CGFloat) { - self.init(top: around, leading: around, bottom: around, trailing: around) - } - - static var zero: Self = .init(around: 0) -} - -// MARK: - Previews - -struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock - - static var previews: some View { - mockTimeline - .previewDisplayName("Mock Timeline") - mockTimeline - .environment(\.layoutDirection, .rightToLeft) - .previewDisplayName("Mock Timeline RTL") - replies - .previewDisplayName("Replies") - threads - .previewDisplayName("Thread decorator") - encryptionAuthenticity - .previewDisplayName("Encryption Indicators") - } - - // These akwats include a reply - static var threads: some View { - ScrollView { - RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(timelineID: ""), - timestamp: "10:42", - isOutgoing: true, - isEditable: false, - canBeRepliedTo: true, - isThreaded: true, - sender: .init(id: "whoever"), - content: .init(body: "A long message that should be on multiple lines."), - replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), - eventID: "123", - eventContent: .message(.text(.init(body: "Short"))))), - groupStyle: .single)) - - AudioRoomTimelineView(timelineItem: .init(id: .init(timelineID: ""), - timestamp: "10:42", - isOutgoing: true, - isEditable: false, - canBeRepliedTo: true, - isThreaded: true, - sender: .init(id: ""), - content: .init(body: "audio.ogg", - duration: 100, - waveform: EstimatedWaveform.mockWaveform, - source: nil, - contentType: nil), - replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), - eventID: "123", - eventContent: .message(.text(.init(body: "Short")))))) - - FileRoomTimelineView(timelineItem: .init(id: .init(timelineID: ""), - timestamp: "10:42", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: true, - sender: .init(id: ""), - content: .init(body: "File", - source: nil, - thumbnailSource: nil, - contentType: nil), - replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), - eventID: "123", - eventContent: .message(.text(.init(body: "Short")))))) - ImageRoomTimelineView(timelineItem: .init(id: .init(timelineID: ""), - timestamp: "10:42", - isOutgoing: true, - isEditable: true, - canBeRepliedTo: true, - isThreaded: true, - sender: .init(id: ""), - content: .init(body: "Some image", source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"), thumbnailSource: nil), - replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), - eventID: "123", - eventContent: .message(.text(.init(body: "Short")))))) - LocationRoomTimelineView(timelineItem: .init(id: .random, - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: true, - sender: .init(id: "Bob"), - content: .init(body: "Fallback geo uri description", - geoURI: .init(latitude: 41.902782, - longitude: 12.496366), - description: "Location description description description description description description description description"), - replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), - eventID: "123", - eventContent: .message(.text(.init(body: "Short")))))) - LocationRoomTimelineView(timelineItem: .init(id: .random, - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: true, - sender: .init(id: "Bob"), - content: .init(body: "Fallback geo uri description", - geoURI: .init(latitude: 41.902782, longitude: 12.496366), description: nil), - replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), - eventID: "123", - eventContent: .message(.text(.init(body: "Short")))))) - - VoiceMessageRoomTimelineView(timelineItem: .init(id: .init(timelineID: ""), - timestamp: "10:42", - isOutgoing: true, - isEditable: false, - canBeRepliedTo: true, - isThreaded: true, - sender: .init(id: ""), - content: .init(body: "audio.ogg", - duration: 100, - waveform: EstimatedWaveform.mockWaveform, - source: nil, - contentType: nil), - replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), - eventID: "123", - eventContent: .message(.text(.init(body: "Short"))))), - playerState: AudioPlayerState(id: .timelineItemIdentifier(.random), duration: 10, waveform: EstimatedWaveform.mockWaveform)) - } - .environmentObject(viewModel.context) - } - - static var mockTimeline: some View { - ScrollView { - VStack(alignment: .leading, spacing: 0) { - ForEach(viewModel.state.timelineViewState.itemViewStates) { viewState in - RoomTimelineItemView(viewState: viewState) - } - } - } - .environmentObject(viewModel.context) - } - - static var replies: some View { - VStack(spacing: 0) { - RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(timelineID: ""), - timestamp: "10:42", - isOutgoing: true, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "whoever"), - content: .init(body: "A long message that should be on multiple lines."), - replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), - eventID: "123", - eventContent: .message(.text(.init(body: "Short"))))), - groupStyle: .single)) - - RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(timelineID: ""), - timestamp: "10:42", - isOutgoing: true, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "whoever"), - content: .init(body: "Short message"), - replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), - eventID: "123", - eventContent: .message(.text(.init(body: "A long message that should be on more than 2 lines and so will be clipped by the layout."))))), - groupStyle: .single)) - } - .environmentObject(viewModel.context) - } - - static var encryptionAuthenticity: some View { - VStack(spacing: 0) { - RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(timelineID: ""), - timestamp: "10:42", - isOutgoing: true, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "whoever"), - content: .init(body: "A long message that should be on multiple lines."), - properties: RoomTimelineItemProperties(encryptionAuthenticity: .unsignedDevice(color: .red))), - groupStyle: .single)) - - RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(timelineID: ""), - timestamp: "10:42", - isOutgoing: true, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "whoever"), - content: .init(body: "A long message that should be on multiple lines."), - properties: RoomTimelineItemProperties(isEdited: true, - encryptionAuthenticity: .unsignedDevice(color: .red))), - groupStyle: .single)) - - RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(timelineID: ""), - timestamp: "10:42", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "whoever"), - content: .init(body: "Short message"), - properties: RoomTimelineItemProperties(encryptionAuthenticity: .unknownDevice(color: .red))), - groupStyle: .first)) - - RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(timelineID: ""), - timestamp: "10:42", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "whoever"), - content: .init(body: "Message goes Here"), - properties: RoomTimelineItemProperties(encryptionAuthenticity: .notGuaranteed(color: .gray))), - groupStyle: .last)) - - ImageRoomTimelineView(timelineItem: ImageRoomTimelineItem(id: .random, - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "Bob"), - content: .init(body: "Some other image", source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"), thumbnailSource: nil), - - properties: RoomTimelineItemProperties(encryptionAuthenticity: .notGuaranteed(color: .gray)))) - - VoiceMessageRoomTimelineView(timelineItem: .init(id: .init(timelineID: ""), - timestamp: "10:42", - isOutgoing: true, - isEditable: false, - canBeRepliedTo: true, - isThreaded: true, - sender: .init(id: ""), - content: .init(body: "audio.ogg", - duration: 100, - waveform: EstimatedWaveform.mockWaveform, - source: nil, - contentType: nil), - properties: RoomTimelineItemProperties(encryptionAuthenticity: .notGuaranteed(color: .gray))), - playerState: AudioPlayerState(id: .timelineItemIdentifier(.random), duration: 10, waveform: EstimatedWaveform.mockWaveform)) - } - .environmentObject(viewModel.context) - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Style/TimelineStyle.swift b/ElementX/Sources/Screens/RoomScreen/View/Style/TimelineStyle.swift deleted file mode 100644 index bc0ca471f4..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Style/TimelineStyle.swift +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation -import SwiftUI - -enum TimelineGroupStyle: Hashable { - case single - case first - case middle - case last - - var shouldShowSenderDetails: Bool { - switch self { - case .single, .first: - return true - default: - return false - } - } -} - -// MARK: - Environment - -private struct TimelineGroupStyleKey: EnvironmentKey { - static let defaultValue = TimelineGroupStyle.single -} - -extension EnvironmentValues { - var timelineGroupStyle: TimelineGroupStyle { - get { self[TimelineGroupStyleKey.self] } - set { self[TimelineGroupStyleKey.self] = newValue } - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Supplementary/TimelineDeliveryStatusView.swift b/ElementX/Sources/Screens/RoomScreen/View/Supplementary/TimelineDeliveryStatusView.swift deleted file mode 100644 index c4b5add299..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Supplementary/TimelineDeliveryStatusView.swift +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Compound -import SwiftUI - -struct TimelineDeliveryStatusView: View { - enum Status { - case sending - case sent - } - - let deliveryStatus: Status - - private var icon: CompoundIcon { - switch deliveryStatus { - case .sending: - return CompoundIcon(\.circle, size: .xSmall, relativeTo: .compound.bodyMD) - case .sent: - return CompoundIcon(\.checkCircle, size: .xSmall, relativeTo: .compound.bodyMD) - } - } - - var body: some View { - icon - .foregroundColor(.compound.iconSecondary) - .accessibilityLabel(accessibilityLabel) - } - - private var accessibilityLabel: String { - switch deliveryStatus { - case .sending: - return L10n.commonSending - case .sent: - return L10n.commonSent - } - } -} - -struct TimelineDeliveryStatusView_Previews: PreviewProvider, TestablePreview { - static var previews: some View { - VStack(spacing: 8) { - TimelineDeliveryStatusView(deliveryStatus: .sending) - TimelineDeliveryStatusView(deliveryStatus: .sent) - } - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Supplementary/TimelineItemStatusView.swift b/ElementX/Sources/Screens/RoomScreen/View/Supplementary/TimelineItemStatusView.swift deleted file mode 100644 index cf400c7ba1..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Supplementary/TimelineItemStatusView.swift +++ /dev/null @@ -1,62 +0,0 @@ -// -// Copyright 2023 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Compound -import SwiftUI - -struct TimelineItemStatusView: View { - let timelineItem: EventBasedTimelineItemProtocol - let adjustedDeliveryStatus: TimelineItemDeliveryStatus? - @EnvironmentObject private var context: RoomScreenViewModel.Context - - private var isLastOutgoingMessage: Bool { - timelineItem.isOutgoing && context.viewState.timelineViewState.timelineIDs.last == timelineItem.id.timelineID - } - - var body: some View { - mainContent - } - - @ViewBuilder - private var mainContent: some View { - if context.viewState.showReadReceipts, !timelineItem.properties.orderedReadReceipts.isEmpty { - readReceipts - } else { - deliveryStatusBadge - } - } - - @ViewBuilder - var deliveryStatusBadge: some View { - switch adjustedDeliveryStatus { - case .sending: - TimelineDeliveryStatusView(deliveryStatus: .sending) - case .sent, .none: - if isLastOutgoingMessage { - // We only display the sent icon for the latest outgoing message - TimelineDeliveryStatusView(deliveryStatus: .sent) - } - case .sendingFailed: - // Bubbles handle the case internally - EmptyView() - } - } - - var readReceipts: some View { - TimelineReadReceiptsView(timelineItem: timelineItem) - .environmentObject(context) - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/SwipeRightAction.swift b/ElementX/Sources/Screens/RoomScreen/View/SwipeRightAction.swift index 70dd0d75d6..09c9286fd3 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/SwipeRightAction.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/SwipeRightAction.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -40,42 +31,7 @@ struct SwipeRightAction: ViewModifier { content .offset(x: xOffset, y: 0.0) .animation(.interactiveSpring().speed(0.5), value: xOffset) - .gesture(DragGesture() - .updating($dragGestureActive) { _, state, _ in - // Available actions should be computed on the fly so we use a gesture state change - // to ask whether the move should be started or not. - state = true - } - .onChanged { value in - guard canStartAction else { - return - } - - // We want to add a spring like behavior to the drag in which the view - // moves slower the more it's dragged. We use a circular easing function - // to generate those values up to the `swipeThreshold` - // The final translation will be between 0 and `swipeThreshold` with the action being enabled from - // `actionThreshold` onwards - let screenWidthNormalisedTranslation = max(0.0, min(value.translation.width, swipeThreshold)) / swipeThreshold - let easedTranslation = circularEaseOut(screenWidthNormalisedTranslation) - xOffset = easedTranslation * xOffsetThreshold - - if xOffset > actionThreshold { - if !hasReachedActionThreshold { - feedbackGenerator.impactOccurred() - hasReachedActionThreshold = true - } - } else { - hasReachedActionThreshold = false - } - } - .onEnded { _ in - if xOffset > actionThreshold { - action() - } - - xOffset = 0.0 - }) + .timelineGesture(gesture) .onChange(of: dragGestureActive) { value in if value == true { if shouldStartAction() { @@ -95,6 +51,55 @@ struct SwipeRightAction: ViewModifier { } } + private var gesture: some Gesture { + DragGesture() + .updating($dragGestureActive) { _, state, _ in + // Available actions should be computed on the fly so we use a gesture state change + // to ask whether the move should be started or not. + state = true + } + .onChanged { value in + guard canStartAction, value.translation.width > value.translation.height else { + return + } + + // Due to https://forums.developer.apple.com/forums/thread/760035 we had to make + // the drag a simultaneous gesture otherwise it was impossible to scroll the timeline. + // Therefore we need to prevent the animation to run if the user is to scrolling vertically. + // It would be nice if we could somehow abort the gesture in this case. + let width: CGFloat = if value.translation.width > abs(value.translation.height) { + value.translation.width + } else { + 0.0 + } + + // We want to add a spring like behaviour to the drag in which the view + // moves slower the more it's dragged. We use a circular easing function + // to generate those values up to the `swipeThreshold` + // The final translation will be between 0 and `swipeThreshold` with the action being enabled from + // `actionThreshold` onwards + let screenWidthNormalisedTranslation = max(0.0, min(width, swipeThreshold)) / swipeThreshold + let easedTranslation = circularEaseOut(screenWidthNormalisedTranslation) + xOffset = easedTranslation * xOffsetThreshold + + if xOffset > actionThreshold { + if !hasReachedActionThreshold { + feedbackGenerator.impactOccurred() + hasReachedActionThreshold = true + } + } else { + hasReachedActionThreshold = false + } + } + .onEnded { _ in + if xOffset > actionThreshold { + action() + } + + xOffset = 0.0 + } + } + /// Used to compute the horizontal translation amount. /// The more it's dragged the less it moves on a circular ease out curve private func circularEaseOut(_ value: Double) -> Double { @@ -108,6 +113,19 @@ extension View { action: @escaping () -> Void) -> some View { modifier(SwipeRightAction(label: label, shouldStartAction: shouldStartAction, action: action)) } + + @ViewBuilder + fileprivate func timelineGesture(_ gesture: some Gesture) -> some View { + // Tchap: don't check for iOS 18 while not using Xcode 16 +// if #available(iOS 18.0, *) { +// // iOS 18 has a bug https://forums.developer.apple.com/forums/thread/760035 and you +// // can't scroll the timeline when `gesture` is used. +// simultaneousGesture(gesture) +// } else { + // Equally on iOS 17 you can't scroll the timeline when `simultaneousGesture` is used. + self.gesture(gesture) +// } + } } struct SwipeRightAction_Previews: PreviewProvider, TestablePreview { diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/AudioRoomTimelineView.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/AudioRoomTimelineView.swift deleted file mode 100644 index 5367a295df..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/AudioRoomTimelineView.swift +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright 2023 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation -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) - } - } -} - -struct AudioRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock - - static var previews: some View { - body.environmentObject(viewModel.context) - } - - static var body: some View { - AudioRoomTimelineView(timelineItem: AudioRoomTimelineItem(id: .random, - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "Bob"), - content: .init(body: "audio.ogg", duration: 300, waveform: nil, source: nil, contentType: nil))) - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/CallInviteRoomTimelineView.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/CallInviteRoomTimelineView.swift deleted file mode 100644 index ec28835fc2..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/CallInviteRoomTimelineView.swift +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright 2024 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Compound -import Foundation -import SwiftUI - -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() - } -} - -struct CallInviteRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock - - static var previews: some View { - body.environmentObject(viewModel.context) - } - - static var body: some View { - CallInviteRoomTimelineView(timelineItem: .init(id: .random, - timestamp: "Now", - isEditable: false, - canBeRepliedTo: false, - sender: .init(id: "Bob"))) - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/FileRoomTimelineView.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/FileRoomTimelineView.swift deleted file mode 100644 index 8fd7d47146..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/FileRoomTimelineView.swift +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation -import SwiftUI - -struct FileRoomTimelineView: View { - let timelineItem: FileRoomTimelineItem - - var body: some View { - TimelineStyler(timelineItem: timelineItem) { - Label(title: { Text(timelineItem.body) }, - icon: { Image(systemName: "doc.text.fill") - .foregroundColor(.compound.iconPrimary) - }) - .labelStyle(RoomTimelineViewLabelStyle()) - .font(.compound.bodyLG) - .padding(.vertical, 12) - .padding(.horizontal, 6) - .accessibilityLabel(L10n.commonFile) - } - } -} - -struct FileRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock - - static var previews: some View { - body.environmentObject(viewModel.context) - } - - static var body: some View { - VStack(spacing: 20.0) { - FileRoomTimelineView(timelineItem: FileRoomTimelineItem(id: .random, - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "Bob"), - content: .init(body: "document.pdf", source: nil, thumbnailSource: nil, contentType: nil))) - - FileRoomTimelineView(timelineItem: FileRoomTimelineItem(id: .random, - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "Bob"), - content: .init(body: "document.docx", source: nil, thumbnailSource: nil, contentType: nil))) - - FileRoomTimelineView(timelineItem: FileRoomTimelineItem(id: .random, - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "Bob"), - content: .init(body: "document.txt", source: nil, thumbnailSource: nil, contentType: nil))) - } - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/HighlightedTimelineItemModifier.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/HighlightedTimelineItemModifier.swift deleted file mode 100644 index 3152077a99..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/HighlightedTimelineItemModifier.swift +++ /dev/null @@ -1,114 +0,0 @@ -// -// Copyright 2024 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Compound -import SwiftUI - -extension View { - func highlightedTimelineItem(_ isHighlighted: Bool) -> some View { - modifier(HighlightedTimelineItemModifier(isHighlighted: isHighlighted)) - } -} - -private struct HighlightedTimelineItemModifier: ViewModifier { - let isHighlighted: Bool - - func body(content: Content) -> some View { - content - .padding(.top, isHighlighted ? 1 : 0) - .background { - if isHighlighted { - VStack(spacing: 0) { - Color.compound._bgBubbleHighlighted - LinearGradient(colors: [.compound._bgBubbleHighlighted, .clear], - startPoint: .top, - endPoint: .bottom) - .frame(maxHeight: 200) - .layoutPriority(1) - } - .overlay(alignment: .top) { - Color.compound.bgAccentRest - .frame(height: 1) - } - } - } - } -} - -// MARK: - Previews - -// swiftlint:disable line_length blanket_disable_command -struct HighlightedTimelineItemModifier_Previews: PreviewProvider, TestablePreview { - static var previews: some View { - ScrollView { - VStack(spacing: 16) { - Bubble(text: "Hello ๐Ÿ‘‹") - .highlightedTimelineItem(true) - - Bubble(text: "Not highlighted") - .highlightedTimelineItem(false) - - // swiftlint:disable line_length - Bubble(text: """ - Bacon ipsum dolor amet brisket bacon hamburger filet mignon ham hock, capicola meatloaf corned beef tongue. Ribeye filet mignon shoulder drumstick doner shank. Landjaeger shankle chislic brisket short loin pig. Frankfurter sirloin jerky bresaola tri-tip cow buffalo. Beef tongue shankle venison, sirloin boudin biltong ham hock corned beef. Sirloin shankle pork belly, strip steak pancetta brisket flank ribeye cow chislic. Pork ham landjaeger, pastrami beef sausage capicola meatball. - - Cow brisket bresaola, burgdoggen cupim turducken sirloin andouille shankle sausage jerky chicken pig. Tail capicola landjaeger frankfurter. Kevin pancetta brisket spare ribs, sausage chuck tail pork. Ground round boudin chuck tri-tip corned beef. Pork belly ham bresaola tail, pork chop meatloaf biltong filet mignon strip steak ribeye boudin shoulder frankfurter. - """, - isOutgoing: true) - .highlightedTimelineItem(true) - // swiftlint:enable line_length - } - } - .previewDisplayName("Layout") - } - - struct Bubble: View { - let text: String - var isOutgoing = false - - var body: some View { - Text(text) - .padding(10) - .background(isOutgoing ? .compound._bgBubbleOutgoing : .compound._bgBubbleIncoming, - in: RoundedRectangle(cornerRadius: 12)) - .padding(isOutgoing ? .leading : .trailing, 40) - .frame(maxWidth: .infinity, alignment: isOutgoing ? .trailing : .leading) - .padding(12) - } - } -} - -/// A preview that allows quick testing of the highlight appearance across various timeline scenarios. -struct HighlightedTimelineItemTimeline_Previews: PreviewProvider { - static let focussedEventID = "RoomTimelineItemFixtures.default.5" - static let viewModel = RoomScreenViewModel(roomProxy: RoomProxyMock(.init(name: "Preview room")), - focussedEventID: focussedEventID, - timelineController: MockRoomTimelineController(), - mediaProvider: MockMediaProvider(), - mediaPlayerProvider: MediaPlayerProviderMock(), - voiceMessageMediaManager: VoiceMessageMediaManagerMock(), - userIndicatorController: ServiceLocator.shared.userIndicatorController, - appMediator: AppMediatorMock.default, - appSettings: ServiceLocator.shared.settings, - analyticsService: ServiceLocator.shared.analytics) - - static var previews: some View { - NavigationStack { - RoomScreen(context: viewModel.context, composerToolbar: ComposerToolbar.mock()) - } - .previewDisplayName("Timeline") - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/PaginationIndicatorRoomTimelineView.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/PaginationIndicatorRoomTimelineView.swift deleted file mode 100644 index 0ab7e51056..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/PaginationIndicatorRoomTimelineView.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import SwiftUI - -struct PaginationIndicatorRoomTimelineView: View { - let timelineItem: PaginationIndicatorRoomTimelineItem - - var body: some View { - ProgressView() - .frame(maxWidth: .infinity) - .padding(.top, 12) // Bottom spacing comes from the next item (date separator). - } -} - -struct PaginationIndicatorRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static var previews: some View { - let item = PaginationIndicatorRoomTimelineItem(position: .start) - PaginationIndicatorRoomTimelineView(timelineItem: item) - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/PollRoomTimelineView.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/PollRoomTimelineView.swift deleted file mode 100644 index d7b830a806..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/PollRoomTimelineView.swift +++ /dev/null @@ -1,80 +0,0 @@ -// -// Copyright 2023 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import SwiftUI - -struct PollRoomTimelineView: View { - let timelineItem: PollRoomTimelineItem - @EnvironmentObject private var context: RoomScreenViewModel.Context - - var body: some View { - TimelineStyler(timelineItem: timelineItem) { - PollView(poll: poll, editable: timelineItem.isEditable) { action in - switch action { - case .selectOption(let optionID): - guard let eventID, let option = poll.options.first(where: { $0.id == optionID }), !option.isSelected else { return } - context.send(viewAction: .handlePollAction(.selectOption(pollStartID: eventID, optionID: option.id))) - case .edit: - guard let eventID else { return } - context.send(viewAction: .handlePollAction(.edit(pollStartID: eventID, poll: poll))) - case .end: - guard let eventID else { return } - context.send(viewAction: .handlePollAction(.end(pollStartID: eventID))) - } - } - } - } - - // MARK: - Private - - private var poll: Poll { - timelineItem.poll - } - - private var eventID: String? { - timelineItem.id.eventID - } -} - -struct PollRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock - - static var previews: some View { - PollRoomTimelineView(timelineItem: .mock(poll: .disclosed(), isOutgoing: false)) - .environmentObject(viewModel.context) - .previewDisplayName("Disclosed, Bubble") - - PollRoomTimelineView(timelineItem: .mock(poll: .undisclosed(), isOutgoing: false)) - .environmentObject(viewModel.context) - .previewDisplayName("Undisclosed, Bubble") - - PollRoomTimelineView(timelineItem: .mock(poll: .endedDisclosed)) - .environmentObject(viewModel.context) - .previewDisplayName("Ended, Disclosed, Bubble") - - PollRoomTimelineView(timelineItem: .mock(poll: .endedUndisclosed)) - .environmentObject(viewModel.context) - .previewDisplayName("Ended, Undisclosed, Bubble") - - PollRoomTimelineView(timelineItem: .mock(poll: .disclosed(createdByAccountOwner: true))) - .environmentObject(viewModel.context) - .previewDisplayName("Creator, disclosed, Bubble") - - PollRoomTimelineView(timelineItem: .mock(poll: .emptyDisclosed, isEditable: true)) - .environmentObject(viewModel.context) - .previewDisplayName("Creator, no votes, Bubble") - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/RedactedRoomTimelineView.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/RedactedRoomTimelineView.swift deleted file mode 100644 index 5537c19e3d..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/RedactedRoomTimelineView.swift +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation -import SwiftUI - -struct RedactedRoomTimelineView: View { - let timelineItem: RedactedRoomTimelineItem - - var body: some View { - TimelineStyler(timelineItem: timelineItem) { - Label(timelineItem.body, icon: \.delete, iconSize: .small, relativeTo: .compound.bodyLG) - .labelStyle(RoomTimelineViewLabelStyle()) - .imageScale(.small) // Smaller icon so that the bubble remains rounded on the outside. - } - } -} - -struct RedactedRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock - - static var previews: some View { - VStack(alignment: .leading, spacing: 20.0) { - RedactedRoomTimelineView(timelineItem: itemWith(text: L10n.commonMessageRemoved, - timestamp: "Later", - senderId: "Anne")) - } - .environmentObject(viewModel.context) - } - - private static func itemWith(text: String, timestamp: String, senderId: String) -> RedactedRoomTimelineItem { - RedactedRoomTimelineItem(id: .random, - body: text, - timestamp: timestamp, - isOutgoing: false, - isEditable: false, - canBeRepliedTo: false, - sender: .init(id: senderId)) - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/SeparatorRoomTimelineView.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/SeparatorRoomTimelineView.swift deleted file mode 100644 index 144af74ffb..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/SeparatorRoomTimelineView.swift +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import SwiftUI - -struct SeparatorRoomTimelineView: View { - let timelineItem: SeparatorRoomTimelineItem - - var body: some View { - Text(timelineItem.text) - .font(.compound.bodySMSemibold) - .foregroundColor(.compound.textPrimary) - .frame(maxWidth: .infinity) - .multilineTextAlignment(.center) - .padding(.horizontal, 36.0) - .padding(.vertical, 8.0) - } -} - -struct SeparatorRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static var previews: some View { - let item = SeparatorRoomTimelineItem(id: .init(timelineID: "Separator"), text: "This is a separator") - SeparatorRoomTimelineView(timelineItem: item) - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/StateRoomTimelineView.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/StateRoomTimelineView.swift deleted file mode 100644 index abe70be593..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/StateRoomTimelineView.swift +++ /dev/null @@ -1,49 +0,0 @@ -// -// Copyright 2023 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import SwiftUI - -struct StateRoomTimelineView: View { - let timelineItem: StateRoomTimelineItem - - var body: some View { - Text(timelineItem.body) - .font(.compound.bodySM) - .multilineTextAlignment(.center) - .foregroundColor(.compound.textSecondary) - .frame(maxWidth: .infinity, alignment: .center) - .padding(.horizontal, 36.0) - .padding(.vertical, 8.0) - } -} - -struct StateRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static var previews: some View { - body - } - - static var body: some View { - StateRoomTimelineView(timelineItem: item) - } - - static let item = StateRoomTimelineItem(id: .random, - body: "Alice joined", - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - sender: .init(id: "")) -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/TextBasedRoomTimelineItem.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/TextBasedRoomTimelineItem.swift deleted file mode 100644 index ee9291c082..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/TextBasedRoomTimelineItem.swift +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright 2023 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation - -protocol TextBasedRoomTimelineItem: EventBasedMessageTimelineItemProtocol { } diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/TextBasedRoomTimelineViewProtocol.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/TextBasedRoomTimelineViewProtocol.swift deleted file mode 100644 index d33bf99329..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/TextBasedRoomTimelineViewProtocol.swift +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright 2023 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -// periphery: ignore - markdown protocol -protocol TextBasedRoomTimelineViewProtocol { - associatedtype TimelineItemType: TextBasedRoomTimelineItem - - var timelineItem: TimelineItemType { get } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/TimelineStartRoomTimelineView.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/TimelineStartRoomTimelineView.swift deleted file mode 100644 index 37ed1098d5..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/TimelineStartRoomTimelineView.swift +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright 2023 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import SwiftUI - -struct TimelineStartRoomTimelineView: View { - let timelineItem: TimelineStartRoomTimelineItem - - var body: some View { - Text(title) - .font(.compound.bodySM) - .foregroundColor(.compound.textSecondary) - .padding(.vertical, 24) - .frame(maxWidth: .infinity) - } - - var title: String { - var text = L10n.screenRoomTimelineBeginningOfRoomNoName - if let name = timelineItem.name { - text = L10n.screenRoomTimelineBeginningOfRoom(name) - } - return text - } -} - -struct TimelineStartRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static var previews: some View { - let item = TimelineStartRoomTimelineItem(name: "Alice and Bob") - TimelineStartRoomTimelineView(timelineItem: item) - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/TimelineView.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/TimelineView.swift deleted file mode 100644 index 5a0b15423a..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/TimelineView.swift +++ /dev/null @@ -1,98 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import SwiftUI -import WysiwygComposer - -/// A table view wrapper that displays the timeline of a room. -struct TimelineView: UIViewControllerRepresentable { - @EnvironmentObject private var viewModelContext: RoomScreenViewModel.Context - - func makeUIViewController(context: Context) -> TimelineTableViewController { - let tableViewController = TimelineTableViewController(coordinator: context.coordinator, - isScrolledToBottom: $viewModelContext.isScrolledToBottom, - scrollToBottomPublisher: viewModelContext.viewState.timelineViewState.scrollToBottomPublisher) - return tableViewController - } - - func updateUIViewController(_ uiViewController: TimelineTableViewController, context: Context) { - context.coordinator.update(tableViewController: uiViewController) - } - - func makeCoordinator() -> Coordinator { - Coordinator(viewModelContext: viewModelContext) - } - - // MARK: - Coordinator - - @MainActor - class Coordinator { - let context: RoomScreenViewModel.Context - - init(viewModelContext: RoomScreenViewModel.Context) { - context = viewModelContext - } - - /// Updates the specified table view's properties from the current view state. - func update(tableViewController: TimelineTableViewController) { - if tableViewController.isSwitchingTimelines != context.viewState.timelineViewState.isSwitchingTimelines { - // Must come before timelineItemsDictionary in order to disable animations. - tableViewController.isSwitchingTimelines = context.viewState.timelineViewState.isSwitchingTimelines - } - if tableViewController.timelineItemsDictionary != context.viewState.timelineViewState.itemsDictionary { - tableViewController.timelineItemsDictionary = context.viewState.timelineViewState.itemsDictionary - } - if tableViewController.paginationState != context.viewState.timelineViewState.paginationState { - tableViewController.paginationState = context.viewState.timelineViewState.paginationState - } - if tableViewController.isLive != context.viewState.timelineViewState.isLive { - tableViewController.isLive = context.viewState.timelineViewState.isLive - } - if tableViewController.focussedEvent != context.viewState.timelineViewState.focussedEvent { - tableViewController.focussedEvent = context.viewState.timelineViewState.focussedEvent - } - - if tableViewController.typingMembers.members != context.viewState.typingMembers { - tableViewController.setTypingMembers(context.viewState.typingMembers) - } - } - - func send(viewAction: RoomScreenViewAction) { - context.send(viewAction: viewAction) - } - } -} - -// MARK: - Previews - -struct TimelineView_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel(roomProxy: RoomProxyMock(.init(id: "stable_id", - name: "Preview room")), - timelineController: MockRoomTimelineController(), - mediaProvider: MockMediaProvider(), - mediaPlayerProvider: MediaPlayerProviderMock(), - voiceMessageMediaManager: VoiceMessageMediaManagerMock(), - userIndicatorController: ServiceLocator.shared.userIndicatorController, - appMediator: AppMediatorMock.default, - appSettings: ServiceLocator.shared.settings, - analyticsService: ServiceLocator.shared.analytics) - - static var previews: some View { - NavigationStack { - RoomScreen(context: viewModel.context, composerToolbar: ComposerToolbar.mock()) - } - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/View/TimelineSenderAvatarView.swift b/ElementX/Sources/Screens/RoomScreen/View/TimelineSenderAvatarView.swift deleted file mode 100644 index f855a953b4..0000000000 --- a/ElementX/Sources/Screens/RoomScreen/View/TimelineSenderAvatarView.swift +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation -import SwiftUI - -struct TimelineSenderAvatarView: View { - @EnvironmentObject private var context: RoomScreenViewModel.Context - - let timelineItem: EventBasedTimelineItemProtocol - - var body: some View { - LoadableAvatarImage(url: timelineItem.sender.avatarURL, - name: timelineItem.sender.displayName, - contentID: timelineItem.sender.id, - avatarSize: .user(on: .timeline), - imageProvider: context.imageProvider) - .overlay { - Circle().stroke(Color.compound.bgCanvasDefault, lineWidth: 3) - } - } -} diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupKeyBackupScreen/SecureBackupKeyBackupScreenCoordinator.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupKeyBackupScreen/SecureBackupKeyBackupScreenCoordinator.swift index c17f1f4af5..91076a07ae 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupKeyBackupScreen/SecureBackupKeyBackupScreenCoordinator.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupKeyBackupScreen/SecureBackupKeyBackupScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupKeyBackupScreen/SecureBackupKeyBackupScreenModels.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupKeyBackupScreen/SecureBackupKeyBackupScreenModels.swift index 729bc1bf94..82660e9971 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupKeyBackupScreen/SecureBackupKeyBackupScreenModels.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupKeyBackupScreen/SecureBackupKeyBackupScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupKeyBackupScreen/SecureBackupKeyBackupScreenViewModel.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupKeyBackupScreen/SecureBackupKeyBackupScreenViewModel.swift index 0f12612ba7..8a8c044e67 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupKeyBackupScreen/SecureBackupKeyBackupScreenViewModel.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupKeyBackupScreen/SecureBackupKeyBackupScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupKeyBackupScreen/SecureBackupKeyBackupScreenViewModelProtocol.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupKeyBackupScreen/SecureBackupKeyBackupScreenViewModelProtocol.swift index 4dcbefa754..ff2e74bf11 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupKeyBackupScreen/SecureBackupKeyBackupScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupKeyBackupScreen/SecureBackupKeyBackupScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupKeyBackupScreen/View/SecureBackupKeyBackupScreen.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupKeyBackupScreen/View/SecureBackupKeyBackupScreen.swift index 9662ebcb8a..d578bcd9b9 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupKeyBackupScreen/View/SecureBackupKeyBackupScreen.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupKeyBackupScreen/View/SecureBackupKeyBackupScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/SecureBackupLogoutConfirmationScreenCoordinator.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/SecureBackupLogoutConfirmationScreenCoordinator.swift index 95e72290d1..0425f6791c 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/SecureBackupLogoutConfirmationScreenCoordinator.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/SecureBackupLogoutConfirmationScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/SecureBackupLogoutConfirmationScreenModels.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/SecureBackupLogoutConfirmationScreenModels.swift index 1901e9676d..2ebfee5446 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/SecureBackupLogoutConfirmationScreenModels.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/SecureBackupLogoutConfirmationScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/SecureBackupLogoutConfirmationScreenViewModel.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/SecureBackupLogoutConfirmationScreenViewModel.swift index bb477ed426..3f52875dff 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/SecureBackupLogoutConfirmationScreenViewModel.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/SecureBackupLogoutConfirmationScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/SecureBackupLogoutConfirmationScreenViewModelProtocol.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/SecureBackupLogoutConfirmationScreenViewModelProtocol.swift index 473626eeac..30b82a4654 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/SecureBackupLogoutConfirmationScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/SecureBackupLogoutConfirmationScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/View/SecureBackupLogoutConfirmationScreen.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/View/SecureBackupLogoutConfirmationScreen.swift index 8f3c6ac3c4..0c682c53c1 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/View/SecureBackupLogoutConfirmationScreen.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupLogoutConfirmationScreen/View/SecureBackupLogoutConfirmationScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/SecureBackupRecoveryKeyScreenCoordinator.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/SecureBackupRecoveryKeyScreenCoordinator.swift index 9e16c3115a..0713b3405c 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/SecureBackupRecoveryKeyScreenCoordinator.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/SecureBackupRecoveryKeyScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/SecureBackupRecoveryKeyScreenModels.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/SecureBackupRecoveryKeyScreenModels.swift index 08488c5ef9..b39de38910 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/SecureBackupRecoveryKeyScreenModels.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/SecureBackupRecoveryKeyScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/SecureBackupRecoveryKeyScreenViewModel.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/SecureBackupRecoveryKeyScreenViewModel.swift index c507f761a0..35a51a48d1 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/SecureBackupRecoveryKeyScreenViewModel.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/SecureBackupRecoveryKeyScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/SecureBackupRecoveryKeyScreenViewModelProtocol.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/SecureBackupRecoveryKeyScreenViewModelProtocol.swift index 30f64e623d..a883ad5551 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/SecureBackupRecoveryKeyScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/SecureBackupRecoveryKeyScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/View/SecureBackupRecoveryKeyScreen.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/View/SecureBackupRecoveryKeyScreen.swift index 06c2c6f99f..f9d17174a6 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/View/SecureBackupRecoveryKeyScreen.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/View/SecureBackupRecoveryKeyScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -205,6 +196,7 @@ struct SecureBackupRecoveryKeyScreen: View { .font(.compound.bodySMSemibold) SecureField(L10n.screenRecoveryKeyConfirmKeyPlaceholder, text: $context.confirmationRecoveryKey) + .tint(.compound.iconAccentTertiary) .frame(maxWidth: .infinity) .padding() .background(Color.compound.bgSubtleSecondaryLevel0) diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/SecureBackupScreenCoordinator.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/SecureBackupScreenCoordinator.swift index c6eb5b20e1..6605642e8f 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/SecureBackupScreenCoordinator.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/SecureBackupScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/SecureBackupScreenModels.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/SecureBackupScreenModels.swift index 5a0c905626..1fa713d1c4 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/SecureBackupScreenModels.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/SecureBackupScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/SecureBackupScreenViewModel.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/SecureBackupScreenViewModel.swift index 62aa73e7de..e3fda71d4d 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/SecureBackupScreenViewModel.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/SecureBackupScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/SecureBackupScreenViewModelProtocol.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/SecureBackupScreenViewModelProtocol.swift index df488d1401..3bdf19fc88 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/SecureBackupScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/SecureBackupScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/View/SecureBackupScreen.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/View/SecureBackupScreen.swift index b74a2b5452..cdc0aa2827 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/View/SecureBackupScreen.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupScreen/View/SecureBackupScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -157,7 +148,7 @@ struct SecureBackupScreen_Previews: PreviewProvider, TestablePreview { } .previewDisplayName("Recovery incomplete") } - .snapshot(delay: 1.0) + .snapshotPreferences(delay: 1.0) } static func viewModel(keyBackupState: SecureBackupKeyBackupState, diff --git a/ElementX/Sources/Screens/Settings/AccountSettings/OIDCAccountSettingsPresenter.swift b/ElementX/Sources/Screens/Settings/AccountSettings/OIDCAccountSettingsPresenter.swift index 273600bd59..c6980de8eb 100644 --- a/ElementX/Sources/Screens/Settings/AccountSettings/OIDCAccountSettingsPresenter.swift +++ b/ElementX/Sources/Screens/Settings/AccountSettings/OIDCAccountSettingsPresenter.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import AuthenticationServices diff --git a/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/AnalyticsSettingsScreenCoordinator.swift b/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/AnalyticsSettingsScreenCoordinator.swift index b2431823a1..adbc714a31 100644 --- a/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/AnalyticsSettingsScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/AnalyticsSettingsScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/AnalyticsSettingsScreenModels.swift b/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/AnalyticsSettingsScreenModels.swift index 85e5953e2b..af290e3c3e 100644 --- a/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/AnalyticsSettingsScreenModels.swift +++ b/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/AnalyticsSettingsScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/AnalyticsSettingsScreenViewModel.swift b/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/AnalyticsSettingsScreenViewModel.swift index 82069c0527..821d0328e1 100644 --- a/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/AnalyticsSettingsScreenViewModel.swift +++ b/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/AnalyticsSettingsScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/AnalyticsSettingsScreenViewModelProtocol.swift b/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/AnalyticsSettingsScreenViewModelProtocol.swift index e073e54243..ed05a0ccd3 100644 --- a/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/AnalyticsSettingsScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/AnalyticsSettingsScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/View/AnalyticsSettingsScreen.swift b/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/View/AnalyticsSettingsScreen.swift index dd31147f12..1972bdabba 100644 --- a/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/View/AnalyticsSettingsScreen.swift +++ b/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/View/AnalyticsSettingsScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/Settings/AvancedOptionsScreen/AdvancedSettingsScreenCoordinator.swift b/ElementX/Sources/Screens/Settings/AvancedOptionsScreen/AdvancedSettingsScreenCoordinator.swift index 4e73b09b37..20715a393f 100644 --- a/ElementX/Sources/Screens/Settings/AvancedOptionsScreen/AdvancedSettingsScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Settings/AvancedOptionsScreen/AdvancedSettingsScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Settings/AvancedOptionsScreen/AdvancedSettingsScreenModels.swift b/ElementX/Sources/Screens/Settings/AvancedOptionsScreen/AdvancedSettingsScreenModels.swift index 65fcb33b94..35f0e8148e 100644 --- a/ElementX/Sources/Screens/Settings/AvancedOptionsScreen/AdvancedSettingsScreenModels.swift +++ b/ElementX/Sources/Screens/Settings/AvancedOptionsScreen/AdvancedSettingsScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/Settings/AvancedOptionsScreen/AdvancedSettingsScreenViewModel.swift b/ElementX/Sources/Screens/Settings/AvancedOptionsScreen/AdvancedSettingsScreenViewModel.swift index 957948cd59..cc7e51a561 100644 --- a/ElementX/Sources/Screens/Settings/AvancedOptionsScreen/AdvancedSettingsScreenViewModel.swift +++ b/ElementX/Sources/Screens/Settings/AvancedOptionsScreen/AdvancedSettingsScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Settings/AvancedOptionsScreen/AdvancedSettingsScreenViewModelProtocol.swift b/ElementX/Sources/Screens/Settings/AvancedOptionsScreen/AdvancedSettingsScreenViewModelProtocol.swift index 0588644eba..b3a079a827 100644 --- a/ElementX/Sources/Screens/Settings/AvancedOptionsScreen/AdvancedSettingsScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/Settings/AvancedOptionsScreen/AdvancedSettingsScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Settings/AvancedOptionsScreen/View/AdvancedSettingsScreen.swift b/ElementX/Sources/Screens/Settings/AvancedOptionsScreen/View/AdvancedSettingsScreen.swift index de350954e7..17436c310a 100644 --- a/ElementX/Sources/Screens/Settings/AvancedOptionsScreen/View/AdvancedSettingsScreen.swift +++ b/ElementX/Sources/Screens/Settings/AvancedOptionsScreen/View/AdvancedSettingsScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenCoordinator.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenCoordinator.swift index 57df849963..e85ceff2f2 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -19,8 +10,6 @@ import SwiftUI enum DeveloperOptionsScreenCoordinatorAction { case clearCache - /// Logout without a confirmation to avoid losing keys when trying SSS. - case forceLogout } final class DeveloperOptionsScreenCoordinator: CoordinatorProtocol { @@ -33,9 +22,10 @@ final class DeveloperOptionsScreenCoordinator: CoordinatorProtocol { actionsSubject.eraseToAnyPublisher() } - init() { + init(isUsingNativeSlidingSync: Bool) { viewModel = DeveloperOptionsScreenViewModel(developerOptions: ServiceLocator.shared.settings, - elementCallBaseURL: ServiceLocator.shared.settings.elementCallBaseURL) + elementCallBaseURL: ServiceLocator.shared.settings.elementCallBaseURL, + isUsingNativeSlidingSync: isUsingNativeSlidingSync) viewModel.actions .sink { [weak self] action in @@ -44,8 +34,6 @@ final class DeveloperOptionsScreenCoordinator: CoordinatorProtocol { switch action { case .clearCache: actionsSubject.send(.clearCache) - case .forceLogout: - actionsSubject.send(.forceLogout) } } .store(in: &cancellables) diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift index a51b15b96b..8ad26e512f 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift @@ -1,30 +1,24 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation enum DeveloperOptionsScreenViewModelAction { case clearCache - /// Logout without a confirmation to avoid losing keys when trying SSS. - case forceLogout } struct DeveloperOptionsScreenViewState: BindableState { let elementCallBaseURL: URL + let isUsingNativeSlidingSync: Bool var bindings: DeveloperOptionsScreenViewStateBindings + + var slidingSyncFooter: String { + "The method used to configure sliding sync when signing in. Changing this setting has no effect until you sign out.\n\nYour current session is using \(isUsingNativeSlidingSync ? "native sliding sync." : "a sliding sync proxy.")" + } } // periphery: ignore - subscripts are seen as false positive @@ -48,12 +42,12 @@ enum DeveloperOptionsScreenViewAction { protocol DeveloperOptionsProtocol: AnyObject { var logLevel: TracingConfiguration.LogLevel { get set } - var simplifiedSlidingSyncEnabled: Bool { get set } + var slidingSyncDiscovery: AppSettings.SlidingSyncDiscovery { get set } var hideUnreadMessagesBadge: Bool { get set } var elementCallBaseURLOverride: URL? { get set } var fuzzyRoomListSearchEnabled: Bool { get set } var pinningEnabled: Bool { get set } - var timelineItemAuthenticityEnabled: Bool { get set } + var invisibleCryptoEnabled: Bool { get set } } extension AppSettings: DeveloperOptionsProtocol { } diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenViewModel.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenViewModel.swift index e6450adc3c..002da920e7 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenViewModel.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -26,21 +17,11 @@ class DeveloperOptionsScreenViewModel: DeveloperOptionsScreenViewModelType, Deve actionsSubject.eraseToAnyPublisher() } - init(developerOptions: DeveloperOptionsProtocol, elementCallBaseURL: URL) { + init(developerOptions: DeveloperOptionsProtocol, elementCallBaseURL: URL, isUsingNativeSlidingSync: Bool) { let bindings = DeveloperOptionsScreenViewStateBindings(developerOptions: developerOptions) - let state = DeveloperOptionsScreenViewState(elementCallBaseURL: elementCallBaseURL, bindings: bindings) + let state = DeveloperOptionsScreenViewState(elementCallBaseURL: elementCallBaseURL, isUsingNativeSlidingSync: isUsingNativeSlidingSync, bindings: bindings) super.init(initialViewState: state) - - context.$viewState - .map(\.bindings.simplifiedSlidingSyncEnabled) - .removeDuplicates() - .dropFirst() // Ignore the initial value received when opening the screen. - .sink { [weak self] isEnabled in - MXLog.error("Toggled simplifiedSlidingSyncEnabled: \(isEnabled). Signing out.") - self?.actionsSubject.send(.forceLogout) - } - .store(in: &cancellables) } override func process(viewAction: DeveloperOptionsScreenViewAction) { diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenViewModelProtocol.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenViewModelProtocol.swift index baedd5e3d6..d0ef557d77 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift index 8dc47cef4c..7f9217f665 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -19,7 +10,12 @@ import SwiftUI struct DeveloperOptionsScreen: View { @ObservedObject var context: DeveloperOptionsScreenViewModel.Context @State private var showConfetti = false - @State private var elementCallBaseURLString = "" + @State private var elementCallURLOverrideString: String + + init(context: DeveloperOptionsScreenViewModel.Context) { + self.context = context + elementCallURLOverrideString = context.elementCallBaseURLOverride?.absoluteString ?? "" + } var body: some View { Form { @@ -27,11 +23,16 @@ struct DeveloperOptionsScreen: View { LogLevelConfigurationView(logLevel: $context.logLevel) } - Section("Sliding Sync") { - Toggle(isOn: $context.simplifiedSlidingSyncEnabled) { - Text("Simplified Sliding Sync") - Text("When toggled you'll be logged out of the app and will need to log in again.") + Section { + Picker("Discovery", selection: $context.slidingSyncDiscovery) { + Text("Proxy only").tag(AppSettings.SlidingSyncDiscovery.proxy) + Text("Automatic").tag(AppSettings.SlidingSyncDiscovery.native) + Text("Force Native โš ๏ธ").tag(AppSettings.SlidingSyncDiscovery.forceNative) } + } header: { + Text("Sliding Sync") + } footer: { + Text(context.viewState.slidingSyncFooter) } Section("Message Pinning") { @@ -51,23 +52,36 @@ struct DeveloperOptionsScreen: View { } } - Section("Encryption") { - Toggle(isOn: $context.timelineItemAuthenticityEnabled) { - Text("Message authenticity warnings") + Section { + Toggle(isOn: $context.invisibleCryptoEnabled) { + Text("Enabled Invisible Crypto") Text("Requires app reboot") } + } header: { + Text("Trust and Decoration") + } footer: { + Text("This setting controls how end-to-end encryption (E2EE) keys are shared. Enabling it will prevent the inclusion of devices that have not been explicitly verified by their owners.") } - - Section("Element Call") { - TextField(context.viewState.elementCallBaseURL.absoluteString, text: $elementCallBaseURLString) + + Section { + TextField(context.viewState.elementCallBaseURL.absoluteString, text: $elementCallURLOverrideString) + .autocorrectionDisabled(true) + .autocapitalization(.none) + .foregroundColor(URL(string: elementCallURLOverrideString) == nil ? .red : .primary) .submitLabel(.done) .onSubmit { - guard let url = URL(string: elementCallBaseURLString) else { return } - context.elementCallBaseURLOverride = url + if elementCallURLOverrideString.isEmpty { + context.elementCallBaseURLOverride = nil + } else if let url = URL(string: elementCallURLOverrideString) { + context.elementCallBaseURLOverride = url + } } - .autocorrectionDisabled(true) - .autocapitalization(.none) - .foregroundColor(URL(string: elementCallBaseURLString) == nil ? .red : .primary) + } header: { + Text("Element Call") + } footer: { + if context.elementCallBaseURLOverride == nil { + Text("The call URL may be overridden by your homeserver.") + } } Section { @@ -167,7 +181,8 @@ private struct LogLevelConfigurationView: View { struct DeveloperOptionsScreen_Previews: PreviewProvider { static let viewModel = DeveloperOptionsScreenViewModel(developerOptions: ServiceLocator.shared.settings, - elementCallBaseURL: ServiceLocator.shared.settings.elementCallBaseURL) + elementCallBaseURL: ServiceLocator.shared.settings.elementCallBaseURL, + isUsingNativeSlidingSync: true) static var previews: some View { NavigationStack { DeveloperOptionsScreen(context: viewModel.context) diff --git a/ElementX/Sources/Screens/Settings/LegalInformationScreen/LegalInformationScreenCoordinator.swift b/ElementX/Sources/Screens/Settings/LegalInformationScreen/LegalInformationScreenCoordinator.swift index 2f5b7c2bd0..e1cc3f8880 100644 --- a/ElementX/Sources/Screens/Settings/LegalInformationScreen/LegalInformationScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Settings/LegalInformationScreen/LegalInformationScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Settings/LegalInformationScreen/LegalInformationScreenModels.swift b/ElementX/Sources/Screens/Settings/LegalInformationScreen/LegalInformationScreenModels.swift index 3c0f744440..3df6a3916f 100644 --- a/ElementX/Sources/Screens/Settings/LegalInformationScreen/LegalInformationScreenModels.swift +++ b/ElementX/Sources/Screens/Settings/LegalInformationScreen/LegalInformationScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/Settings/LegalInformationScreen/LegalInformationScreenViewModel.swift b/ElementX/Sources/Screens/Settings/LegalInformationScreen/LegalInformationScreenViewModel.swift index 1e59ebaee8..b77c9d885c 100644 --- a/ElementX/Sources/Screens/Settings/LegalInformationScreen/LegalInformationScreenViewModel.swift +++ b/ElementX/Sources/Screens/Settings/LegalInformationScreen/LegalInformationScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Settings/LegalInformationScreen/LegalInformationScreenViewModelProtocol.swift b/ElementX/Sources/Screens/Settings/LegalInformationScreen/LegalInformationScreenViewModelProtocol.swift index d11c539454..b3ca788651 100644 --- a/ElementX/Sources/Screens/Settings/LegalInformationScreen/LegalInformationScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/Settings/LegalInformationScreen/LegalInformationScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Settings/LegalInformationScreen/View/LegalInformationScreen.swift b/ElementX/Sources/Screens/Settings/LegalInformationScreen/View/LegalInformationScreen.swift index d4d0361fce..caec82eb23 100644 --- a/ElementX/Sources/Screens/Settings/LegalInformationScreen/View/LegalInformationScreen.swift +++ b/ElementX/Sources/Screens/Settings/LegalInformationScreen/View/LegalInformationScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/NotificationSettingsEditScreenCoordinator.swift b/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/NotificationSettingsEditScreenCoordinator.swift index 7ba042bd9c..c44a33f1dd 100644 --- a/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/NotificationSettingsEditScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/NotificationSettingsEditScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -57,7 +48,7 @@ final class NotificationSettingsEditScreenCoordinator: CoordinatorProtocol { // MARK: - Private private func presentRoomNotificationSettings(roomID: String) async { - guard let roomProxy = await parameters.userSession.clientProxy.roomForIdentifier(roomID) else { return } + guard case let .joined(roomProxy) = await parameters.userSession.clientProxy.roomForIdentifier(roomID) else { return } let roomNotificationSettingsParameters = RoomNotificationSettingsScreenCoordinatorParameters(navigationStackCoordinator: parameters.navigationStackCoordinator, notificationSettingsProxy: parameters.notificationSettings, diff --git a/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/NotificationSettingsEditScreenModels.swift b/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/NotificationSettingsEditScreenModels.swift index 8caecab81f..89def2e252 100644 --- a/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/NotificationSettingsEditScreenModels.swift +++ b/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/NotificationSettingsEditScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/NotificationSettingsEditScreenViewModel.swift b/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/NotificationSettingsEditScreenViewModel.swift index defb98dcdb..c47f71a2d6 100644 --- a/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/NotificationSettingsEditScreenViewModel.swift +++ b/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/NotificationSettingsEditScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -44,7 +35,7 @@ class NotificationSettingsEditScreenViewModel: NotificationSettingsEditScreenVie super.init(initialViewState: NotificationSettingsEditScreenViewState(bindings: bindings, strings: NotificationSettingsEditScreenStrings(chatType: chatType)), - imageProvider: userSession.mediaProvider) + mediaProvider: userSession.mediaProvider) setupNotificationSettingsSubscription() setupRoomSummaryProviderSubscription() @@ -138,7 +129,7 @@ class NotificationSettingsEditScreenViewModel: NotificationSettingsEditScreenVie var roomsWithUserDefinedMode: [NotificationSettingsEditScreenRoom] = [] for roomSummary in filteredRoomsSummary { - guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomSummary.id) else { continue } + guard case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomSummary.id) else { continue } // `isOneToOneRoom` here is not the same as `isDirect` on the room. From the point of view of the push rule, a one-to-one room is a room with exactly two active members. let isOneToOneRoom = roomProxy.activeMembersCount == 2 // display only the rooms we're interested in diff --git a/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/NotificationSettingsEditScreenViewModelProtocol.swift b/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/NotificationSettingsEditScreenViewModelProtocol.swift index 60f46b8063..740211b824 100644 --- a/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/NotificationSettingsEditScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/NotificationSettingsEditScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/View/NotificationSettingsEditScreen.swift b/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/View/NotificationSettingsEditScreen.swift index 3849f2b1fd..fed827263c 100644 --- a/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/View/NotificationSettingsEditScreen.swift +++ b/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/View/NotificationSettingsEditScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/View/NotificationSettingsEditScreenRoomCell.swift b/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/View/NotificationSettingsEditScreenRoomCell.swift index 0db0f696b8..73d94d5b2f 100644 --- a/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/View/NotificationSettingsEditScreenRoomCell.swift +++ b/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/View/NotificationSettingsEditScreenRoomCell.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -41,7 +32,7 @@ struct NotificationSettingsEditScreenRoomCell: View { if dynamicTypeSize < .accessibility3 { RoomAvatarImage(avatar: room.avatar, avatarSize: .room(on: .notificationSettings), - imageProvider: context.imageProvider) + mediaProvider: context.mediaProvider) .dynamicTypeSize(dynamicTypeSize < .accessibility1 ? dynamicTypeSize : .accessibility1) .accessibilityHidden(true) } diff --git a/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/NotificationSettingsScreenCoordinator.swift b/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/NotificationSettingsScreenCoordinator.swift index 01d1c94e44..9235b0f93a 100644 --- a/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/NotificationSettingsScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/NotificationSettingsScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/NotificationSettingsScreenModels.swift b/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/NotificationSettingsScreenModels.swift index 89ad7e5b7f..8f837dfd84 100644 --- a/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/NotificationSettingsScreenModels.swift +++ b/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/NotificationSettingsScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/NotificationSettingsScreenViewModel.swift b/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/NotificationSettingsScreenViewModel.swift index 8082ddc650..1bd872fd82 100644 --- a/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/NotificationSettingsScreenViewModel.swift +++ b/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/NotificationSettingsScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/NotificationSettingsScreenViewModelProtocol.swift b/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/NotificationSettingsScreenViewModelProtocol.swift index 418527361d..f93731a91d 100644 --- a/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/NotificationSettingsScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/NotificationSettingsScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/View/NotificationSettingsScreen.swift b/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/View/NotificationSettingsScreen.swift index 8b78137b7f..dca3369aac 100644 --- a/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/View/NotificationSettingsScreen.swift +++ b/ElementX/Sources/Screens/Settings/NotificationSettingsScreen/View/NotificationSettingsScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -262,9 +253,9 @@ struct NotificationSettingsScreen_Previews: PreviewProvider, TestablePreview { static var previews: some View { NotificationSettingsScreen(context: viewModel.context) - .snapshot(delay: 2.0) + .snapshotPreferences(delay: 2.0) NotificationSettingsScreen(context: viewModelConfigurationMismatch.context) - .snapshot(delay: 2.0) + .snapshotPreferences(delay: 2.0) .previewDisplayName("Configuration mismatch") } } diff --git a/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenCoordinator.swift b/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenCoordinator.swift index 61a17ad960..d1ac3ee8d1 100644 --- a/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -36,6 +27,7 @@ enum SettingsScreenCoordinatorAction { case notifications case advancedSettings case developerOptions + case deactivateAccount } final class SettingsScreenCoordinator: CoordinatorProtocol { @@ -84,6 +76,8 @@ final class SettingsScreenCoordinator: CoordinatorProtocol { actionsSubject.send(.developerOptions) case .logout: actionsSubject.send(.logout) + case .deactivateAccount: + actionsSubject.send(.deactivateAccount) } } .store(in: &cancellables) diff --git a/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenModels.swift b/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenModels.swift index 3fc6117297..f16b531c9c 100644 --- a/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenModels.swift +++ b/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -31,6 +22,7 @@ enum SettingsScreenViewModelAction: Equatable { case advancedSettings case developerOptions case logout + case deactivateAccount } enum SettingsScreenSecuritySectionMode { @@ -43,6 +35,7 @@ struct SettingsScreenViewState: BindableState { var userID: String var accountProfileURL: URL? var accountSessionsListURL: URL? + var showAccountDeactivation: Bool var userAvatarURL: URL? var userDisplayName: String? var showDeveloperOptions: Bool @@ -51,6 +44,12 @@ struct SettingsScreenViewState: BindableState { var showSecuritySectionBadge = false var showBlockedUsers = false + + var bindings = SettingsScreenViewStateBindings() +} + +struct SettingsScreenViewStateBindings { + var isPresentingAccountDeactivationConfirmation = false } enum SettingsScreenViewAction { @@ -68,4 +67,5 @@ enum SettingsScreenViewAction { case developerOptions case advancedSettings case logout + case deactivateAccount } diff --git a/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenViewModel.swift b/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenViewModel.swift index d8dfd5ba62..d9001b3e51 100644 --- a/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenViewModel.swift +++ b/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -29,8 +20,9 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo init(userSession: UserSessionProtocol) { super.init(initialViewState: .init(deviceID: userSession.clientProxy.deviceID, userID: userSession.clientProxy.userID, + showAccountDeactivation: userSession.clientProxy.canDeactivateAccount, showDeveloperOptions: AppSettings.isDevelopmentBuild), - imageProvider: userSession.mediaProvider) + mediaProvider: userSession.mediaProvider) userSession.clientProxy.userAvatarURLPublisher .receive(on: DispatchQueue.main) @@ -114,6 +106,8 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo state.showDeveloperOptions = true case .developerOptions: actionsSubject.send(.developerOptions) + case .deactivateAccount: + actionsSubject.send(.deactivateAccount) } } } diff --git a/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenViewModelProtocol.swift b/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenViewModelProtocol.swift index d934c43e68..4e60d6b933 100644 --- a/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Settings/SettingsScreen/View/SettingsScreen.swift b/ElementX/Sources/Screens/Settings/SettingsScreen/View/SettingsScreen.swift index fa38cdbde0..efe901dbcd 100644 --- a/ElementX/Sources/Screens/Settings/SettingsScreen/View/SettingsScreen.swift +++ b/ElementX/Sources/Screens/Settings/SettingsScreen/View/SettingsScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -38,6 +29,8 @@ struct SettingsScreen: View { } generalSection + + signOutSection } .compoundList() .navigationTitle(L10n.commonSettings) @@ -56,7 +49,7 @@ struct SettingsScreen: View { name: context.viewState.userDisplayName, contentID: context.viewState.userID, avatarSize: .user(on: .settings), - imageProvider: context.imageProvider) + mediaProvider: context.mediaProvider) .accessibilityHidden(true) VStack(alignment: .leading, spacing: 2) { @@ -176,7 +169,11 @@ struct SettingsScreen: View { }) .accessibilityIdentifier(A11yIdentifiers.settingsScreen.developerOptions) } - + } + } + + private var signOutSection: some View { + Section { ListRow(label: .action(title: L10n.screenSignoutPreferenceItem, icon: \.signOut, role: .destructive), @@ -184,6 +181,15 @@ struct SettingsScreen: View { context.send(viewAction: .logout) }) .accessibilityIdentifier(A11yIdentifiers.settingsScreen.logout) + + if context.viewState.showAccountDeactivation { + ListRow(label: .action(title: L10n.actionDeactivateAccount, + icon: \.warning, + role: .destructive), + kind: .navigationLink { + context.send(viewAction: .deactivateAccount) + }) + } } footer: { VStack(spacing: 0) { versionText @@ -233,7 +239,7 @@ struct SettingsScreen_Previews: PreviewProvider, TestablePreview { static var previews: some View { NavigationStack { SettingsScreen(context: viewModel.context) - .snapshot(delay: 1.0) + .snapshotPreferences(delay: 1.0) } } } diff --git a/ElementX/Sources/Screens/Settings/UserDetailsEditScreen/UserDetailsEditScreenCoordinator.swift b/ElementX/Sources/Screens/Settings/UserDetailsEditScreen/UserDetailsEditScreenCoordinator.swift index 188e3b5079..b4eb6e3361 100644 --- a/ElementX/Sources/Screens/Settings/UserDetailsEditScreen/UserDetailsEditScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Settings/UserDetailsEditScreen/UserDetailsEditScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Settings/UserDetailsEditScreen/UserDetailsEditScreenModels.swift b/ElementX/Sources/Screens/Settings/UserDetailsEditScreen/UserDetailsEditScreenModels.swift index c4c49d5ca9..3148646d17 100644 --- a/ElementX/Sources/Screens/Settings/UserDetailsEditScreen/UserDetailsEditScreenModels.swift +++ b/ElementX/Sources/Screens/Settings/UserDetailsEditScreen/UserDetailsEditScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/Settings/UserDetailsEditScreen/UserDetailsEditScreenViewModel.swift b/ElementX/Sources/Screens/Settings/UserDetailsEditScreen/UserDetailsEditScreenViewModel.swift index d9ea18e348..f83b911fda 100644 --- a/ElementX/Sources/Screens/Settings/UserDetailsEditScreen/UserDetailsEditScreenViewModel.swift +++ b/ElementX/Sources/Screens/Settings/UserDetailsEditScreen/UserDetailsEditScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -36,7 +27,7 @@ class UserDetailsEditScreenViewModel: UserDetailsEditScreenViewModelType, UserDe self.userIndicatorController = userIndicatorController super.init(initialViewState: UserDetailsEditScreenViewState(userID: clientProxy.userID, - bindings: .init()), imageProvider: mediaProvider) + bindings: .init()), mediaProvider: mediaProvider) clientProxy.userAvatarURLPublisher .receive(on: DispatchQueue.main) diff --git a/ElementX/Sources/Screens/Settings/UserDetailsEditScreen/UserDetailsEditScreenViewModelProtocol.swift b/ElementX/Sources/Screens/Settings/UserDetailsEditScreen/UserDetailsEditScreenViewModelProtocol.swift index bfeefd9c91..4fed300a49 100644 --- a/ElementX/Sources/Screens/Settings/UserDetailsEditScreen/UserDetailsEditScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/Settings/UserDetailsEditScreen/UserDetailsEditScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/Settings/UserDetailsEditScreen/View/UserDetailsEditScreen.swift b/ElementX/Sources/Screens/Settings/UserDetailsEditScreen/View/UserDetailsEditScreen.swift index f3d57b6edd..ed6a29f866 100644 --- a/ElementX/Sources/Screens/Settings/UserDetailsEditScreen/View/UserDetailsEditScreen.swift +++ b/ElementX/Sources/Screens/Settings/UserDetailsEditScreen/View/UserDetailsEditScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -64,7 +55,7 @@ struct UserDetailsEditScreen: View { name: context.viewState.currentDisplayName, contentID: context.viewState.userID, avatarSize: .user(on: .editUserDetails), - imageProvider: context.imageProvider) + mediaProvider: context.mediaProvider) .overlay(alignment: .bottomTrailing) { avatarOverlayIcon } diff --git a/ElementX/Sources/Screens/StartChatScreen/StartChatScreenCoordinator.swift b/ElementX/Sources/Screens/StartChatScreen/StartChatScreenCoordinator.swift index df1a79a7da..56791a1a4a 100644 --- a/ElementX/Sources/Screens/StartChatScreen/StartChatScreenCoordinator.swift +++ b/ElementX/Sources/Screens/StartChatScreen/StartChatScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/StartChatScreen/StartChatScreenModels.swift b/ElementX/Sources/Screens/StartChatScreen/StartChatScreenModels.swift index 7d7e7966ea..6113180dc8 100644 --- a/ElementX/Sources/Screens/StartChatScreen/StartChatScreenModels.swift +++ b/ElementX/Sources/Screens/StartChatScreen/StartChatScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/StartChatScreen/StartChatScreenViewModel.swift b/ElementX/Sources/Screens/StartChatScreen/StartChatScreenViewModel.swift index a609c01257..ef64b2e5d7 100644 --- a/ElementX/Sources/Screens/StartChatScreen/StartChatScreenViewModel.swift +++ b/ElementX/Sources/Screens/StartChatScreen/StartChatScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -41,7 +32,7 @@ class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenVie self.userIndicatorController = userIndicatorController self.userDiscoveryService = userDiscoveryService - super.init(initialViewState: StartChatScreenViewState(userID: userSession.clientProxy.userID), imageProvider: userSession.mediaProvider) + super.init(initialViewState: StartChatScreenViewState(userID: userSession.clientProxy.userID), mediaProvider: userSession.mediaProvider) setupBindings() diff --git a/ElementX/Sources/Screens/StartChatScreen/StartChatScreenViewModelProtocol.swift b/ElementX/Sources/Screens/StartChatScreen/StartChatScreenViewModelProtocol.swift index 86210a5fde..a24042823b 100644 --- a/ElementX/Sources/Screens/StartChatScreen/StartChatScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/StartChatScreen/StartChatScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/StartChatScreen/View/StartChatScreen.swift b/ElementX/Sources/Screens/StartChatScreen/View/StartChatScreen.swift index 735817d091..48a06919af 100644 --- a/ElementX/Sources/Screens/StartChatScreen/View/StartChatScreen.swift +++ b/ElementX/Sources/Screens/StartChatScreen/View/StartChatScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -90,7 +81,7 @@ struct StartChatScreen: View { ForEach(context.viewState.usersSection.users, id: \.userID) { user in UserProfileListRow(user: user, membership: nil, - imageProvider: context.imageProvider, + mediaProvider: context.mediaProvider, kind: .button { context.send(viewAction: .selectUser(user)) }) diff --git a/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift b/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift new file mode 100644 index 0000000000..b4ad60281e --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift @@ -0,0 +1,568 @@ +// +// Copyright 2023, 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Combine +import UIKit + +enum TimelineInteractionHandlerAction { + case composer(action: TimelineComposerAction) + + case displayEmojiPicker(itemID: TimelineItemIdentifier, selectedEmojis: Set) + case displayReportContent(itemID: TimelineItemIdentifier, senderID: String) + case displayMessageForwarding(itemID: TimelineItemIdentifier) + case displayMediaUploadPreviewScreen(url: URL) + case displayPollForm(mode: PollFormMode) + + case showActionMenu(TimelineItemActionMenuInfo) + case showDebugInfo(TimelineItemDebugInfo) + + case displayAudioRecorderPermissionError + case displayErrorToast(String) + + case viewInRoomTimeline(eventID: String) +} + +@MainActor +class TimelineInteractionHandler { + private let roomProxy: JoinedRoomProxyProtocol + private let timelineController: RoomTimelineControllerProtocol + private let mediaProvider: MediaProviderProtocol + private let mediaPlayerProvider: MediaPlayerProviderProtocol + private let voiceMessageRecorder: VoiceMessageRecorderProtocol + private let voiceMessageMediaManager: VoiceMessageMediaManagerProtocol + private let userIndicatorController: UserIndicatorControllerProtocol + private let appMediator: AppMediatorProtocol + private let appSettings: AppSettings + private let analyticsService: AnalyticsService + private let pollInteractionHandler: PollInteractionHandlerProtocol + + private let actionsSubject: PassthroughSubject = .init() + var actions: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + private var voiceMessageRecorderObserver: AnyCancellable? { + didSet { + appMediator.setIdleTimerDisabled(voiceMessageRecorderObserver != nil) + } + } + + private var resumeVoiceMessagePlaybackAfterScrubbing = false + + init(roomProxy: JoinedRoomProxyProtocol, + timelineController: RoomTimelineControllerProtocol, + mediaProvider: MediaProviderProtocol, + mediaPlayerProvider: MediaPlayerProviderProtocol, + voiceMessageMediaManager: VoiceMessageMediaManagerProtocol, + voiceMessageRecorder: VoiceMessageRecorderProtocol, + userIndicatorController: UserIndicatorControllerProtocol, + appMediator: AppMediatorProtocol, + appSettings: AppSettings, + analyticsService: AnalyticsService) { + self.roomProxy = roomProxy + self.timelineController = timelineController + self.mediaProvider = mediaProvider + self.mediaPlayerProvider = mediaPlayerProvider + self.voiceMessageMediaManager = voiceMessageMediaManager + self.voiceMessageRecorder = voiceMessageRecorder + self.userIndicatorController = userIndicatorController + self.appMediator = appMediator + self.appSettings = appSettings + self.analyticsService = analyticsService + pollInteractionHandler = PollInteractionHandler(analyticsService: analyticsService, roomProxy: roomProxy) + } + + // MARK: Timeline Item Action Menu + + func displayTimelineItemActionMenu(for itemID: TimelineItemIdentifier) { + Task { + guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID), + let eventTimelineItem = timelineItem as? EventBasedTimelineItemProtocol else { + // Don't show a menu for non-event based items. + return + } + + actionsSubject.send(.composer(action: .removeFocus)) + actionsSubject.send(.showActionMenu(.init(item: eventTimelineItem))) + } + } + + func handleTimelineItemMenuAction(_ action: TimelineItemMenuAction, itemID: TimelineItemIdentifier) { + guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID), + let eventTimelineItem = timelineItem as? EventBasedTimelineItemProtocol else { + return + } + + switch action { + case .copy: + guard let messageTimelineItem = timelineItem as? EventBasedMessageTimelineItemProtocol else { + return + } + + UIPasteboard.general.string = messageTimelineItem.body + case .edit: + switch timelineItem { + case let messageTimelineItem as EventBasedMessageTimelineItemProtocol: + processEditMessageEvent(messageTimelineItem) + case let pollTimelineItem as PollRoomTimelineItem: + guard let eventID = pollTimelineItem.id.eventID else { + MXLog.error("Cannot edit poll with id: \(timelineItem.id)") + return + } + actionsSubject.send(.displayPollForm(mode: .edit(eventID: eventID, poll: pollTimelineItem.poll))) + default: + MXLog.error("Cannot edit item with id: \(timelineItem.id)") + } + case .copyPermalink: + guard let eventID = eventTimelineItem.id.eventID else { + actionsSubject.send(.displayErrorToast(L10n.errorFailedCreatingThePermalink)) + return + } + + Task { + guard case let .success(permalinkURL) = await roomProxy.matrixToEventPermalink(eventID) else { + actionsSubject.send(.displayErrorToast(L10n.errorFailedCreatingThePermalink)) + return + } + + UIPasteboard.general.url = permalinkURL + } + case .redact: + Task { + await timelineController.redact(itemID) + } + case .reply: + 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) + + actionsSubject.send(.composer(action: .setMode(mode: .reply(itemID: eventTimelineItem.id, replyDetails: replyDetails, isThread: replyInfo.isThread)))) + case .forward(let itemID): + actionsSubject.send(.displayMessageForwarding(itemID: itemID)) + case .viewSource: + let debugInfo = timelineController.debugInfo(for: eventTimelineItem.id) + MXLog.info("Showing debug info for \(eventTimelineItem.id)") + actionsSubject.send(.showDebugInfo(debugInfo)) + case .retryDecryption(let sessionID): + Task { + await timelineController.retryDecryption(for: sessionID) + } + case .report: + actionsSubject.send(.displayReportContent(itemID: itemID, senderID: eventTimelineItem.sender.id)) + case .react: + displayEmojiPicker(for: itemID) + case .toggleReaction(let key): + Task { await timelineController.toggleReaction(key, to: itemID) } + case .endPoll(let pollStartID): + endPoll(pollStartID: pollStartID) + case .pin: + analyticsService.trackPinUnpinEvent(.init(from: timelineController.timelineKind == .pinned ? .MessagePinningList : .Timeline, + kind: .Pin)) + guard let eventID = itemID.eventID else { return } + Task { await timelineController.pin(eventID: eventID) } + case .unpin: + analyticsService.trackPinUnpinEvent(.init(from: timelineController.timelineKind == .pinned ? .MessagePinningList : .Timeline, + kind: .Unpin)) + guard let eventID = itemID.eventID else { return } + Task { await timelineController.unpin(eventID: eventID) } + case .viewInRoomTimeline: + analyticsService.trackInteraction(name: .PinnedMessageListViewTimeline) + guard let eventID = itemID.eventID else { return } + actionsSubject.send(.viewInRoomTimeline(eventID: eventID)) + } + + if action.switchToDefaultComposer { + actionsSubject.send(.composer(action: .setMode(mode: .default))) + } + } + + private func processEditMessageEvent(_ messageTimelineItem: EventBasedMessageTimelineItemProtocol) { + let text: String + var htmlText: String? + switch messageTimelineItem.contentType { + case .text(let content): + text = content.body + htmlText = content.formattedBodyHTMLString + case .emote(let content): + text = "/me " + content.body + 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(originalItemId: messageTimelineItem.id)))) + actionsSubject.send(.composer(action: .setText(plainText: text, htmlText: htmlText))) + } + + // MARK: Polls + + func sendPollResponse(pollStartID: String, optionID: String) { + Task { + let sendPollResponseResult = await pollInteractionHandler.sendPollResponse(pollStartID: pollStartID, optionID: optionID) + + switch sendPollResponseResult { + case .success: + break + case .failure: + actionsSubject.send(.displayErrorToast(L10n.errorUnknown)) + } + } + } + + func endPoll(pollStartID: String) { + Task { + let endPollResult = await pollInteractionHandler.endPoll(pollStartID: pollStartID) + + switch endPollResult { + case .success: + break + case .failure: + actionsSubject.send(.displayErrorToast(L10n.errorUnknown)) + } + } + } + + // 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)") + } + } + } + } + + // MARK: Voice messages + + private func handleVoiceMessageRecorderAction(_ action: VoiceMessageRecorderAction) { + MXLog.debug("handling voice recorder action: \(action) - (audio)") + switch action { + case .didStartRecording(let audioRecorder): + let audioRecordState = AudioRecorderState() + audioRecordState.attachAudioRecorder(audioRecorder) + actionsSubject.send(.composer(action: .setMode(mode: .recordVoiceMessage(state: audioRecordState)))) + case .didStopRecording(let previewAudioPlayerState, let url): + actionsSubject.send(.composer(action: .setMode(mode: .previewVoiceMessage(state: previewAudioPlayerState, waveform: .url(url), isUploading: false)))) + voiceMessageRecorderObserver = nil + case .didFailWithError(let error): + switch error { + case .audioRecorderError(.recordPermissionNotGranted): + MXLog.info("permission to record audio has not been granted.") + actionsSubject.send(.displayAudioRecorderPermissionError) + default: + MXLog.error("failed to start voice message recording. \(error)") + actionsSubject.send(.composer(action: .setMode(mode: .default))) + } + } + } + + func startRecordingVoiceMessage() async { + voiceMessageRecorderObserver = voiceMessageRecorder.actions + .receive(on: DispatchQueue.main) + .sink { [weak self] action in + self?.handleVoiceMessageRecorderAction(action) + } + + await voiceMessageRecorder.startRecording() + } + + func stopRecordingVoiceMessage() async { + await voiceMessageRecorder.stopRecording() + } + + func cancelRecordingVoiceMessage() async { + await voiceMessageRecorder.cancelRecording() + voiceMessageRecorderObserver = nil + actionsSubject.send(.composer(action: .setMode(mode: .default))) + } + + func deleteCurrentVoiceMessage() async { + if voiceMessageRecorder.isRecording { + await voiceMessageRecorder.cancelRecording() + } else { + await voiceMessageRecorder.deleteRecording() + } + + voiceMessageRecorderObserver = nil + actionsSubject.send(.composer(action: .setMode(mode: .default))) + } + + func sendCurrentVoiceMessage() async { + guard let audioPlayerState = voiceMessageRecorder.previewAudioPlayerState, let recordingURL = voiceMessageRecorder.recordingURL else { + actionsSubject.send(.displayErrorToast(L10n.errorFailedUploadingVoiceMessage)) + return + } + + analyticsService.trackComposer(inThread: false, + isEditing: false, + isReply: false, + messageType: .VoiceMessage, + startsThread: nil) + + actionsSubject.send(.composer(action: .setMode(mode: .previewVoiceMessage(state: audioPlayerState, waveform: .url(recordingURL), isUploading: true)))) + await voiceMessageRecorder.stopPlayback() + switch await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy, audioConverter: AudioConverter()) { + case .success: + await deleteCurrentVoiceMessage() + case .failure(let error): + MXLog.error("failed to send the voice message. \(error)") + actionsSubject.send(.composer(action: .setMode(mode: .previewVoiceMessage(state: audioPlayerState, waveform: .url(recordingURL), isUploading: false)))) + actionsSubject.send(.displayErrorToast(L10n.errorFailedUploadingVoiceMessage)) + } + } + + func startPlayingRecordedVoiceMessage() async { + await mediaPlayerProvider.detachAllStates(except: voiceMessageRecorder.previewAudioPlayerState) + if case .failure(let error) = await voiceMessageRecorder.startPlayback() { + MXLog.error("failed to play recorded voice message. \(error)") + } + } + + func pausePlayingRecordedVoiceMessage() { + voiceMessageRecorder.pausePlayback() + } + + func seekRecordedVoiceMessage(to progress: Double) async { + await mediaPlayerProvider.detachAllStates(except: voiceMessageRecorder.previewAudioPlayerState) + await voiceMessageRecorder.seekPlayback(to: progress) + } + + func scrubVoiceMessagePlayback(scrubbing: Bool) async { + guard let audioPlayerState = voiceMessageRecorder.previewAudioPlayerState else { + return + } + if scrubbing { + if audioPlayerState.playbackState == .playing { + resumeVoiceMessagePlaybackAfterScrubbing = true + pausePlayingRecordedVoiceMessage() + } + } else { + if resumeVoiceMessagePlaybackAfterScrubbing { + resumeVoiceMessagePlaybackAfterScrubbing = false + await startPlayingRecordedVoiceMessage() + } + } + } + + // MARK: Audio Playback + + // swiftlint:disable:next cyclomatic_complexity + func playPauseAudio(for itemID: TimelineItemIdentifier) async { + MXLog.info("Toggle play/pause audio for itemID \(itemID)") + guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID) else { + fatalError("TimelineItem \(itemID) not found") + } + + guard let voiceMessageRoomTimelineItem = timelineItem as? VoiceMessageRoomTimelineItem else { + fatalError("Invalid TimelineItem type for itemID \(itemID) (expecting `VoiceMessageRoomTimelineItem` but found \(type(of: timelineItem)) instead") + } + + guard let source = voiceMessageRoomTimelineItem.content.source else { + MXLog.error("Cannot start voice message playback, source is not defined for itemID \(itemID)") + 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 + } + + // Stop any recording in progress + if voiceMessageRecorder.isRecording { + await voiceMessageRecorder.stopRecording() + } + + guard let audioPlayerState = audioPlayerState(for: itemID) else { + fatalError("Audio player state not found for \(itemID)") + } + + // Ensure this one is attached + if !audioPlayerState.isAttached { + audioPlayerState.attachAudioPlayer(audioPlayer) + } + + // Detach all other states + await mediaPlayerProvider.detachAllStates(except: audioPlayerState) + + guard audioPlayer.mediaSource == source, audioPlayer.state != .error else { + // Load content + do { + MXLog.info("Loading voice message audio content from source for itemID \(itemID)") + let url = try await voiceMessageMediaManager.loadVoiceMessageFromSource(source, body: nil) + + // 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) + } + } catch { + MXLog.error("Failed to load voice message: \(error)") + audioPlayerState.reportError() + } + + return + } + + if audioPlayer.state == .playing { + audioPlayer.pause() + } else { + audioPlayer.play() + } + } + + func seekAudio(for itemID: TimelineItemIdentifier, progress: Double) async { + guard let playerState = mediaPlayerProvider.playerState(for: .timelineItemIdentifier(itemID)) else { + return + } + await mediaPlayerProvider.detachAllStates(except: playerState) + await playerState.updateState(progress: progress) + } + + func audioPlayerState(for itemID: TimelineItemIdentifier) -> AudioPlayerState? { + guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID) else { + MXLog.error("TimelineItem \(itemID) not found") + return nil + } + + guard let voiceMessageRoomTimelineItem = timelineItem as? VoiceMessageRoomTimelineItem else { + MXLog.error("Invalid TimelineItem type (expecting `VoiceMessageRoomTimelineItem` but found \(type(of: timelineItem)) instead") + return nil + } + + if let playerState = mediaPlayerProvider.playerState(for: .timelineItemIdentifier(itemID)) { + return playerState + } + + let playerState = AudioPlayerState(id: .timelineItemIdentifier(itemID), + title: L10n.commonVoiceMessage, + duration: voiceMessageRoomTimelineItem.content.duration, + waveform: voiceMessageRoomTimelineItem.content.waveform) + mediaPlayerProvider.register(audioPlayerState: playerState) + return playerState + } + + // MARK: Other + + func displayEmojiPicker(for itemID: TimelineItemIdentifier) { + guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID), + timelineItem.isReactable, + let eventTimelineItem = timelineItem as? EventBasedTimelineItemProtocol else { + return + } + let selectedEmojis = Set(eventTimelineItem.properties.reactions.compactMap { $0.isHighlighted ? $0.key : nil }) + actionsSubject.send(.displayEmojiPicker(itemID: itemID, selectedEmojis: selectedEmojis)) + } + + func processItemTap(_ itemID: TimelineItemIdentifier) async -> RoomTimelineControllerAction { + guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID) else { + return .none + } + + switch timelineItem { + case let item as LocationRoomTimelineItem: + guard let geoURI = item.content.geoURI else { return .none } + return .displayLocation(body: item.content.body, geoURI: geoURI, description: item.content.description) + default: + return await displayMediaActionIfPossible(timelineItem: timelineItem) + } + } + + // MARK: - Private + + private func buildReplyInfo(for item: EventBasedTimelineItemProtocol) -> ReplyInfo { + switch item { + case let messageItem as EventBasedMessageTimelineItemProtocol: + return .init(type: .message(messageItem.contentType), isThread: messageItem.isThreaded) + case let pollItem as PollRoomTimelineItem: + return .init(type: .poll(question: pollItem.poll.question), isThread: false) + default: + return .init(type: .message(.text(.init(body: item.body))), isThread: false) + } + } + + private func displayMediaActionIfPossible(timelineItem: RoomTimelineItemProtocol) async -> RoomTimelineControllerAction { + var source: MediaSourceProxy? + var body: String + + switch timelineItem { + case let item as ImageRoomTimelineItem: + source = item.content.source + body = item.content.body + case let item as VideoRoomTimelineItem: + source = item.content.source + body = item.content.body + case let item as FileRoomTimelineItem: + source = item.content.source + body = item.content.body + case let item as AudioRoomTimelineItem: + // For now we are just displaying audio messages with the File preview until we create a timeline player for them. + source = item.content.source + body = item.content.body + default: + return .none + } + + guard let source else { return .none } + switch await mediaProvider.loadFileFromSource(source, body: body) { + case .success(let file): + return .displayMediaFile(file: file, title: body) + case .failure: + return .none + } + } +} + +private struct ReplyInfo { + let type: TimelineEventContent + let isThread: Bool +} diff --git a/ElementX/Sources/Screens/Timeline/TimelineModels.swift b/ElementX/Sources/Screens/Timeline/TimelineModels.swift new file mode 100644 index 0000000000..fc64307211 --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/TimelineModels.swift @@ -0,0 +1,222 @@ +// +// 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 OrderedCollections +import SwiftUI + +enum TimelineViewModelAction { + case displayEmojiPicker(itemID: TimelineItemIdentifier, selectedEmojis: Set) + case displayReportContent(itemID: TimelineItemIdentifier, senderID: String) + case displayCameraPicker + case displayMediaPicker + case displayDocumentPicker + case displayLocationPicker + case displayPollForm(mode: PollFormMode) + case displayMediaUploadPreviewScreen(url: URL) + case tappedOnSenderDetails(userID: String) + case displayMessageForwarding(forwardingItem: MessageForwardingItem) + case displayLocation(body: String, geoURI: GeoURI, description: String?) + case displayResolveSendFailure(failure: TimelineItemSendFailure.VerifiedUser, itemID: TimelineItemIdentifier) + case composer(action: TimelineComposerAction) + case hasScrolled(direction: ScrollDirection) + case viewInRoomTimeline(eventID: String) +} + +enum TimelineViewPollAction { + case selectOption(pollStartID: String, optionID: String) + case end(pollStartID: String) + case edit(pollStartID: String, poll: Poll) +} + +enum TimelineAudioPlayerAction { + case playPause(itemID: TimelineItemIdentifier) + case seek(itemID: TimelineItemIdentifier, progress: Double) +} + +enum TimelineViewAction { + case itemAppeared(itemID: TimelineItemIdentifier) + case itemDisappeared(itemID: TimelineItemIdentifier) + + case itemTapped(itemID: TimelineItemIdentifier) + case itemSendInfoTapped(itemID: TimelineItemIdentifier) + case toggleReaction(key: String, itemID: TimelineItemIdentifier) + case sendReadReceiptIfNeeded(TimelineItemIdentifier) + case paginateBackwards + case paginateForwards + case scrollToBottom + + case displayTimelineItemMenu(itemID: TimelineItemIdentifier) + case handleTimelineItemMenuAction(itemID: TimelineItemIdentifier, action: TimelineItemMenuAction) + + case tappedOnSenderDetails(userID: String) + case displayReactionSummary(itemID: TimelineItemIdentifier, key: String) + case displayEmojiPicker(itemID: TimelineItemIdentifier) + case displayReadReceipts(itemID: TimelineItemIdentifier) + + case handlePasteOrDrop(provider: NSItemProvider) + case handlePollAction(TimelineViewPollAction) + case handleAudioPlayerAction(TimelineAudioPlayerAction) + + /// Focus the timeline onto the specified event ID (switching to a detached timeline if needed). + case focusOnEventID(String) + /// Switch back to a live timeline (from a detached one). + case focusLive + /// The timeline scrolled to reveal the focussed item. + case scrolledToFocussedItem + /// The table view has loaded the first items for a new timeline. + case hasSwitchedTimeline + + case hasScrolled(direction: ScrollDirection) + case setOpenURLAction(OpenURLAction) +} + +enum TimelineComposerAction { + case setMode(mode: ComposerMode) + case setText(plainText: String, htmlText: String?) + case removeFocus + case clear +} + +struct TimelineViewState: BindableState { + let isPinnedEventsTimeline: Bool + var roomID: String + var members: [String: RoomMemberState] = [:] + var typingMembers: [String] = [] + var showLoading = false + var showReadReceipts = false + var isEncryptedOneToOneRoom = false + var timelineViewState: TimelineState // check the doc before changing this + + var ownUserID: String + var canCurrentUserRedactOthers = false + var canCurrentUserRedactSelf = false + var canCurrentUserPin = false + var isViewSourceEnabled: Bool + + // The `pinnedEventIDs` are used only to determine if an item is already pinned or not. + // It's updated from the room info, so it's faster than using the timeline + var pinnedEventIDs: Set = [] + + /// an openURL closure which opens URLs first using the App's environment rather than skipping out to external apps + var openURL: OpenURLAction? + + var bindings: TimelineViewStateBindings + + /// A closure providing the associated audio player state for an item in the timeline. + var audioPlayerStateProvider: (@MainActor (_ itemId: TimelineItemIdentifier) -> AudioPlayerState?)? +} + +struct TimelineViewStateBindings { + var isScrolledToBottom = true + + /// The state of wether reactions listed on the timeline are expanded/collapsed. + /// Key is itemID, value is the collapsed state. + var reactionsCollapsed: [TimelineItemIdentifier: Bool] + + /// A media item that will be previewed with QuickLook. + var mediaPreviewItem: MediaPreviewItem? + + var alertInfo: AlertInfo? + + var debugInfo: TimelineItemDebugInfo? + + var actionMenuInfo: TimelineItemActionMenuInfo? + + var reactionSummaryInfo: ReactionSummaryInfo? + + var readReceiptsSummaryInfo: ReadReceiptSummaryInfo? +} + +struct TimelineItemActionMenuInfo: Equatable, Identifiable { + static func == (lhs: TimelineItemActionMenuInfo, rhs: TimelineItemActionMenuInfo) -> Bool { + lhs.id == rhs.id + } + + let item: EventBasedTimelineItemProtocol + + var id: TimelineItemIdentifier { + item.id + } +} + +struct ReactionSummaryInfo: Identifiable { + let reactions: [AggregatedReaction] + let selectedKey: String + + var id: String { + selectedKey + } +} + +struct ReadReceiptSummaryInfo: Identifiable { + let orderedReceipts: [ReadReceipt] + let id: TimelineItemIdentifier +} + +enum RoomScreenAlertInfoType: Hashable { + case audioRecodingPermissionError + case pollEndConfirmation(String) + case sendingFailed + case encryptionAuthenticity(String) +} + +struct RoomMemberState { + let displayName: String? + let avatarURL: URL? +} + +/// Used as the state for the TimelineView, to avoid having the context continuously refresh the list of items on each small change. +/// Is also nice to have this as a wrapper for any state that is directly connected to the timeline. +struct TimelineState { + var isLive = true + var paginationState = PaginationState.initial + + /// The room is in the process of loading items from a new timeline (switching to/from a detached timeline). + var isSwitchingTimelines = false + + struct FocussedEvent: Equatable { + enum Appearance { + /// The event should be shown using an animated scroll. + case animated + /// The event should be shown immediately, without any animation. + case immediate + /// The event has already been shown. + case hasAppeared + } + + /// The ID of the event. + let eventID: String + /// How the event should be shown, or whether it has already appeared. + var appearance: Appearance + } + + /// A focussed event that was navigated to via a permalink. + var focussedEvent: FocussedEvent? + + // These can be removed when we have full swiftUI and moved as @State values in the view + var scrollToBottomPublisher = PassthroughSubject() + + var itemsDictionary = OrderedDictionary() + + var timelineIDs: [String] { + itemsDictionary.keys.elements + } + + var itemViewStates: [RoomTimelineItemViewState] { + itemsDictionary.values.elements + } + + func hasLoadedItem(with eventID: String) -> Bool { + itemViewStates.contains { $0.identifier.eventID == eventID } + } +} + +enum ScrollDirection: Equatable { + case top + case bottom +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/TimelineTableViewController.swift b/ElementX/Sources/Screens/Timeline/TimelineTableViewController.swift similarity index 95% rename from ElementX/Sources/Screens/RoomScreen/View/Timeline/TimelineTableViewController.swift rename to ElementX/Sources/Screens/Timeline/TimelineTableViewController.swift index 42994abe28..b85fbb3fdb 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/TimelineTableViewController.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineTableViewController.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -127,7 +118,7 @@ class TimelineTableViewController: UIViewController { var isSwitchingTimelines = false /// The focussed event if navigating to an event permalink within the room. - var focussedEvent: TimelineViewState.FocussedEvent? { + var focussedEvent: TimelineState.FocussedEvent? { didSet { guard let focussedEvent, focussedEvent.appearance != .hasAppeared else { return } scrollToItem(eventID: focussedEvent.eventID, animated: focussedEvent.appearance == .animated) @@ -140,7 +131,7 @@ class TimelineTableViewController: UIViewController { /// Updates the typing members but also updates table view items func setTypingMembers(_ members: [String]) { DispatchQueue.main.async { - // Avoid `Publishing changes from within view update warnings` + // Avoid `Publishing changes from within view update` warnings self.typingMembers.members = members } } @@ -182,7 +173,7 @@ class TimelineTableViewController: UIViewController { tableView.separatorStyle = .none tableView.allowsSelection = false tableView.keyboardDismissMode = .onDrag - tableView.backgroundColor = UIColor(.compound.bgCanvasDefault) + tableView.backgroundColor = .compound.bgCanvasDefault tableView.transform = CGAffineTransform(scaleX: 1, y: -1) view.addSubview(tableView) @@ -283,7 +274,7 @@ class TimelineTableViewController: UIViewController { .id(id) .frame(maxWidth: .infinity, alignment: .leading) .environmentObject(coordinator.context) // Attempted fix at a crash in TimelineItemContextMenu - .environment(\.roomContext, coordinator.context) + .environment(\.timelineContext, coordinator.context) } .margins(.all, 0) // Margins are handled in the stylers .minSize(height: 1) @@ -317,8 +308,12 @@ class TimelineTableViewController: UIViewController { guard let dataSource else { return } var snapshot = NSDiffableDataSourceSnapshot() - snapshot.appendSections([.typingIndicator]) - snapshot.appendItems([TimelineTypingIndicatorCell.reuseIdentifier]) + + // We don't want to display the typing notification in this timeline + if !coordinator.context.viewState.isPinnedEventsTimeline { + snapshot.appendSections([.typingIndicator]) + snapshot.appendItems([TimelineTypingIndicatorCell.reuseIdentifier]) + } snapshot.appendSections([.main]) snapshot.appendItems(timelineItemsIDs) diff --git a/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift b/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift new file mode 100644 index 0000000000..623b5d4121 --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift @@ -0,0 +1,895 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Algorithms +import Combine +import MatrixRustSDK +import OrderedCollections +import SwiftUI + +typealias TimelineViewModelType = StateStoreViewModel + +class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { + private enum Constants { + static let paginationEventLimit: UInt16 = 20 + static let detachedTimelineSize: UInt16 = 100 + static let focusTimelineToastIndicatorID = "RoomScreenFocusTimelineToastIndicator" + static let toastErrorID = "RoomScreenToastError" + } + + private let roomProxy: JoinedRoomProxyProtocol + private let timelineController: RoomTimelineControllerProtocol + private let mediaPlayerProvider: MediaPlayerProviderProtocol + private let userIndicatorController: UserIndicatorControllerProtocol + private let appMediator: AppMediatorProtocol + private let appSettings: AppSettings + private let analyticsService: AnalyticsService + + private let timelineInteractionHandler: TimelineInteractionHandler + + private let composerFocusedSubject = PassthroughSubject() + + private let actionsSubject: PassthroughSubject = .init() + var actions: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + private var paginateBackwardsTask: Task? + private var paginateForwardsTask: Task? + + init(roomProxy: JoinedRoomProxyProtocol, + focussedEventID: String? = nil, + timelineController: RoomTimelineControllerProtocol, + mediaProvider: MediaProviderProtocol, + mediaPlayerProvider: MediaPlayerProviderProtocol, + voiceMessageMediaManager: VoiceMessageMediaManagerProtocol, + userIndicatorController: UserIndicatorControllerProtocol, + appMediator: AppMediatorProtocol, + appSettings: AppSettings, + analyticsService: AnalyticsService) { + self.timelineController = timelineController + self.mediaPlayerProvider = mediaPlayerProvider + self.roomProxy = roomProxy + self.appSettings = appSettings + self.analyticsService = analyticsService + self.userIndicatorController = userIndicatorController + self.appMediator = appMediator + + let voiceMessageRecorder = VoiceMessageRecorder(audioRecorder: AudioRecorder(), mediaPlayerProvider: mediaPlayerProvider) + + timelineInteractionHandler = TimelineInteractionHandler(roomProxy: roomProxy, + timelineController: timelineController, + mediaProvider: mediaProvider, + mediaPlayerProvider: mediaPlayerProvider, + voiceMessageMediaManager: voiceMessageMediaManager, + voiceMessageRecorder: voiceMessageRecorder, + userIndicatorController: userIndicatorController, + appMediator: appMediator, + appSettings: appSettings, + analyticsService: analyticsService) + + super.init(initialViewState: TimelineViewState(isPinnedEventsTimeline: timelineController.timelineKind == .pinned, + roomID: roomProxy.id, + isEncryptedOneToOneRoom: roomProxy.isEncryptedOneToOneRoom, + timelineViewState: TimelineState(focussedEvent: focussedEventID.map { .init(eventID: $0, appearance: .immediate) }), + ownUserID: roomProxy.ownUserID, + isViewSourceEnabled: appSettings.viewSourceEnabled, + bindings: .init(reactionsCollapsed: [:])), + mediaProvider: mediaProvider) + + if focussedEventID != nil { + // The timeline controller will start loading a detached timeline. + showFocusLoadingIndicator() + } + + Task { + await updatePinnedEventIDs() + } + + setupSubscriptions() + setupDirectRoomSubscriptionsIfNeeded() + + // Set initial values for redacting from the macOS context menu. + Task { await updatePermissions() } + + state.audioPlayerStateProvider = { [weak self] itemID -> AudioPlayerState? in + guard let self else { + return nil + } + + return self.timelineInteractionHandler.audioPlayerState(for: itemID) + } + + buildTimelineViews(timelineItems: timelineController.timelineItems) + + updateMembers(roomProxy.membersPublisher.value) + + // Note: beware if we get to e.g. restore a reply / edit, + // maybe we are tracking a non-needed first initial state + trackComposerMode(.default) + } + + // MARK: - Public + + func stop() { + // Work around QLPreviewController dismissal issues, see the InteractiveQuickLookModifier. + state.bindings.mediaPreviewItem = nil + } + + override func process(viewAction: TimelineViewAction) { + switch viewAction { + case .itemAppeared(let id): + Task { await timelineController.processItemAppearance(id) } + case .itemDisappeared(let id): + Task { await timelineController.processItemDisappearance(id) } + case .itemTapped(let id): + Task { await handleItemTapped(with: id) } + case .itemSendInfoTapped(let itemID): + handleItemSendInfoTapped(itemID: itemID) + case .toggleReaction(let emoji, let itemId): + Task { await timelineController.toggleReaction(emoji, to: itemId) } + case .sendReadReceiptIfNeeded(let lastVisibleItemID): + Task { await sendReadReceiptIfNeeded(for: lastVisibleItemID) } + case .paginateBackwards: + paginateBackwards() + case .paginateForwards: + paginateForwards() + case .scrollToBottom: + scrollToBottom() + case .displayTimelineItemMenu(let itemID): + timelineInteractionHandler.displayTimelineItemActionMenu(for: itemID) + case .handleTimelineItemMenuAction(let itemID, let action): + timelineInteractionHandler.handleTimelineItemMenuAction(action, itemID: itemID) + case .tappedOnSenderDetails(userID: let userID): + actionsSubject.send(.tappedOnSenderDetails(userID: userID)) + case .displayEmojiPicker(let itemID): + timelineInteractionHandler.displayEmojiPicker(for: itemID) + case .displayReactionSummary(let itemID, let key): + displayReactionSummary(for: itemID, selectedKey: key) + case .displayReadReceipts(itemID: let itemID): + displayReadReceipts(for: itemID) + case .handlePasteOrDrop(let provider): + timelineInteractionHandler.handlePasteOrDrop(provider) + case .handlePollAction(let pollAction): + handlePollAction(pollAction) + case .handleAudioPlayerAction(let audioPlayerAction): + handleAudioPlayerAction(audioPlayerAction) + case .focusOnEventID(let eventID): + Task { await focusOnEvent(eventID: eventID) } + case .focusLive: + focusLive() + case .scrolledToFocussedItem: + didScrollToFocussedItem() + case .hasSwitchedTimeline: + Task { state.timelineViewState.isSwitchingTimelines = false } + case let .hasScrolled(direction): + actionsSubject.send(.hasScrolled(direction: direction)) + case .setOpenURLAction(let action): + state.openURL = action + } + } + + func process(composerAction: ComposerToolbarViewModelAction) { + switch composerAction { + case .sendMessage(let message, let html, let mode, let intentionalMentions): + Task { + await sendCurrentMessage(message, + html: html, + mode: mode, + intentionalMentions: intentionalMentions) + } + case .editLastMessage: + editLastMessage() + case .attach(let attachment): + attach(attachment) + case .handlePasteOrDrop(let provider): + timelineInteractionHandler.handlePasteOrDrop(provider) + case .composerModeChanged(mode: let mode): + trackComposerMode(mode) + case .composerFocusedChanged(isFocused: let isFocused): + composerFocusedSubject.send(isFocused) + case .voiceMessage(let voiceMessageAction): + processVoiceMessageAction(voiceMessageAction) + case .contentChanged(let isEmpty): + guard appSettings.sharePresence else { + return + } + + Task { + await roomProxy.sendTypingNotification(isTyping: !isEmpty) + } + } + } + + func focusOnEvent(eventID: String) async { + if state.timelineViewState.hasLoadedItem(with: eventID) { + state.timelineViewState.focussedEvent = .init(eventID: eventID, appearance: .animated) + return + } + + showFocusLoadingIndicator() + defer { hideFocusLoadingIndicator() } + + switch await timelineController.focusOnEvent(eventID, timelineSize: Constants.detachedTimelineSize) { + case .success: + state.timelineViewState.focussedEvent = .init(eventID: eventID, appearance: .immediate) + case .failure(let error): + MXLog.error("Failed to focus on event \(eventID)") + + if case .eventNotFound = error { + displayErrorToast(L10n.errorMessageNotFound) + } else { + displayErrorToast(L10n.commonFailed) + } + } + } + + // MARK: - Private + + private func focusLive() { + timelineController.focusLive() + } + + private func didScrollToFocussedItem() { + if var focussedEvent = state.timelineViewState.focussedEvent { + focussedEvent.appearance = .hasAppeared + state.timelineViewState.focussedEvent = focussedEvent + hideFocusLoadingIndicator() + } + } + + private func editLastMessage() { + guard let item = timelineController.timelineItems.reversed().first(where: { + guard let item = $0 as? EventBasedMessageTimelineItemProtocol else { + return false + } + + return item.sender.id == roomProxy.ownUserID && item.isEditable + }) else { + return + } + + timelineInteractionHandler.handleTimelineItemMenuAction(.edit, itemID: item.id) + } + + private func attach(_ attachment: ComposerAttachmentType) { + switch attachment { + case .camera: + actionsSubject.send(.displayCameraPicker) + case .photoLibrary: + actionsSubject.send(.displayMediaPicker) + case .file: + actionsSubject.send(.displayDocumentPicker) + case .location: + actionsSubject.send(.displayLocationPicker) + case .poll: + actionsSubject.send(.displayPollForm(mode: .new)) + } + } + + private func handlePollAction(_ action: TimelineViewPollAction) { + switch action { + case let .selectOption(pollStartID, optionID): + timelineInteractionHandler.sendPollResponse(pollStartID: pollStartID, optionID: optionID) + case let .end(pollStartID): + displayAlert(.pollEndConfirmation(pollStartID)) + case .edit(let pollStartID, let poll): + actionsSubject.send(.displayPollForm(mode: .edit(eventID: pollStartID, poll: poll))) + } + } + + private func handleAudioPlayerAction(_ action: TimelineAudioPlayerAction) { + switch action { + case .playPause(let itemID): + Task { await timelineInteractionHandler.playPauseAudio(for: itemID) } + case .seek(let itemID, let progress): + Task { await timelineInteractionHandler.seekAudio(for: itemID, progress: progress) } + } + } + + private func processVoiceMessageAction(_ action: ComposerToolbarVoiceMessageAction) { + switch action { + case .startRecording: + Task { + await mediaPlayerProvider.detachAllStates(except: nil) + await timelineInteractionHandler.startRecordingVoiceMessage() + } + case .stopRecording: + Task { await timelineInteractionHandler.stopRecordingVoiceMessage() } + case .cancelRecording: + Task { await timelineInteractionHandler.cancelRecordingVoiceMessage() } + case .deleteRecording: + Task { await timelineInteractionHandler.deleteCurrentVoiceMessage() } + case .send: + Task { await timelineInteractionHandler.sendCurrentVoiceMessage() } + case .startPlayback: + Task { await timelineInteractionHandler.startPlayingRecordedVoiceMessage() } + case .pausePlayback: + timelineInteractionHandler.pausePlayingRecordedVoiceMessage() + case .seekPlayback(let progress): + Task { await timelineInteractionHandler.seekRecordedVoiceMessage(to: progress) } + case .scrubPlayback(let scrubbing): + Task { await timelineInteractionHandler.scrubVoiceMessagePlayback(scrubbing: scrubbing) } + } + } + + private func updateMembers(_ members: [RoomMemberProxyProtocol]) { + state.members = members.reduce(into: [String: RoomMemberState]()) { dictionary, member in + dictionary[member.userID] = RoomMemberState(displayName: member.displayName, avatarURL: member.avatarURL) + } + } + + private func updatePermissions() async { + if case let .success(value) = await roomProxy.canUserRedactOther(userID: roomProxy.ownUserID) { + state.canCurrentUserRedactOthers = value + } else { + state.canCurrentUserRedactOthers = false + } + + if case let .success(value) = await roomProxy.canUserRedactOwn(userID: roomProxy.ownUserID) { + state.canCurrentUserRedactSelf = value + } else { + state.canCurrentUserRedactSelf = false + } + + if appSettings.pinningEnabled, + case let .success(value) = await roomProxy.canUserPinOrUnpin(userID: roomProxy.ownUserID) { + state.canCurrentUserPin = value + } else { + state.canCurrentUserPin = false + } + } + + private func setupSubscriptions() { + timelineController.callbacks + .receive(on: DispatchQueue.main) + .sink { [weak self] callback in + guard let self else { return } + + switch callback { + case .updatedTimelineItems(let updatedItems, let isSwitchingTimelines): + buildTimelineViews(timelineItems: updatedItems, isSwitchingTimelines: isSwitchingTimelines) + case .paginationState(let paginationState): + if state.timelineViewState.paginationState != paginationState { + state.timelineViewState.paginationState = paginationState + } + case .isLive(let isLive): + if state.timelineViewState.isLive != isLive { + state.timelineViewState.isLive = isLive + + // Remove the event highlight *only* when transitioning from non-live to live. + if isLive, state.timelineViewState.focussedEvent != nil { + state.timelineViewState.focussedEvent = nil + } + } + } + } + .store(in: &cancellables) + + let roomInfoSubscription = roomProxy + .actionsPublisher + .filter { $0 == .roomInfoUpdate } + Task { [weak self] in + for await _ in roomInfoSubscription.receive(on: DispatchQueue.main).values { + guard !Task.isCancelled else { + return + } + await self?.updatePinnedEventIDs() + await self?.updatePermissions() + } + } + .store(in: &cancellables) + + setupAppSettingsSubscriptions() + + roomProxy.membersPublisher + .receive(on: DispatchQueue.main) + .sink { [weak self] in self?.updateMembers($0) } + .store(in: &cancellables) + + roomProxy.typingMembersPublisher + .receive(on: DispatchQueue.main) + .filter { [weak self] _ in self?.appSettings.sharePresence ?? false } + .weakAssign(to: \.state.typingMembers, on: self) + .store(in: &cancellables) + + timelineInteractionHandler.actions + .receive(on: DispatchQueue.main) + .sink { [weak self] action in + guard let self else { return } + + switch action { + case .composer(let action): + actionsSubject.send(.composer(action: action)) + case .displayAudioRecorderPermissionError: + displayAlert(.audioRecodingPermissionError) + case .displayErrorToast(let title): + displayErrorToast(title) + case .displayEmojiPicker(let itemID, let selectedEmojis): + actionsSubject.send(.displayEmojiPicker(itemID: itemID, selectedEmojis: selectedEmojis)) + case .displayMessageForwarding(let itemID): + Task { await self.forwardMessage(itemID: itemID) } + case .displayPollForm(let mode): + actionsSubject.send(.displayPollForm(mode: mode)) + case .displayReportContent(let itemID, let senderID): + actionsSubject.send(.displayReportContent(itemID: itemID, senderID: senderID)) + case .displayMediaUploadPreviewScreen(let url): + actionsSubject.send(.displayMediaUploadPreviewScreen(url: url)) + case .showActionMenu(let actionMenuInfo): + Task { + await self.updatePermissions() + self.state.bindings.actionMenuInfo = actionMenuInfo + } + case .showDebugInfo(let debugInfo): + state.bindings.debugInfo = debugInfo + case .viewInRoomTimeline(let eventID): + actionsSubject.send(.viewInRoomTimeline(eventID: eventID)) + } + } + .store(in: &cancellables) + } + + private func setupAppSettingsSubscriptions() { + appSettings.$sharePresence + .weakAssign(to: \.state.showReadReceipts, on: self) + .store(in: &cancellables) + + appSettings.$viewSourceEnabled + .weakAssign(to: \.state.isViewSourceEnabled, on: self) + .store(in: &cancellables) + } + + private func updatePinnedEventIDs() async { + if appSettings.pinningEnabled { + state.pinnedEventIDs = await roomProxy.pinnedEventIDs + } + } + + private func setupDirectRoomSubscriptionsIfNeeded() { + guard roomProxy.isDirect else { + return + } + + let shouldShowInviteAlert = composerFocusedSubject + .removeDuplicates() + .map { [weak self] isFocused in + guard let self else { return false } + + return isFocused && self.roomProxy.isUserAloneInDirectRoom + } + // We want to show the alert just once, so we are taking the first "true" emitted + .first { $0 } + + shouldShowInviteAlert + .sink { [weak self] _ in + self?.showInviteAlert() + } + .store(in: &cancellables) + } + + private func paginateBackwards() { + guard paginateBackwardsTask == nil else { + return + } + + paginateBackwardsTask = Task { [weak self] in + guard let self else { + return + } + + switch await timelineController.paginateBackwards(requestSize: Constants.paginationEventLimit) { + case .failure: + displayErrorToast(L10n.errorFailedLoadingMessages) + default: + break + } + paginateBackwardsTask = nil + } + } + + private func paginateForwards() { + guard paginateForwardsTask == nil else { + return + } + + paginateForwardsTask = Task { [weak self] in + guard let self else { + return + } + + switch await timelineController.paginateForwards(requestSize: Constants.paginationEventLimit) { + case .failure: + displayErrorToast(L10n.errorFailedLoadingMessages) + default: + break + } + + if state.timelineViewState.paginationState.forward == .timelineEndReached { + focusLive() + } + + paginateForwardsTask = nil + } + } + + private func scrollToBottom() { + if state.timelineViewState.isLive { + state.timelineViewState.scrollToBottomPublisher.send(()) + } else { + focusLive() + } + } + + private func sendReadReceiptIfNeeded(for lastVisibleItemID: TimelineItemIdentifier) async { + guard appMediator.appState == .active else { return } + + await timelineController.sendReadReceipt(for: lastVisibleItemID) + } + + private func handleItemTapped(with itemID: TimelineItemIdentifier) async { + state.showLoading = true + let action = await timelineInteractionHandler.processItemTap(itemID) + + switch action { + case .displayMediaFile(let file, let title): + actionsSubject.send(.composer(action: .removeFocus)) // Hide the keyboard otherwise a big white space is sometimes shown when dismissing the preview. + state.bindings.mediaPreviewItem = MediaPreviewItem(file: file, title: title) + case .displayLocation(let body, let geoURI, let description): + actionsSubject.send(.displayLocation(body: body, geoURI: geoURI, description: description)) + case .none: + break + } + state.showLoading = false + } + + private func handleItemSendInfoTapped(itemID: TimelineItemIdentifier) { + guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID) else { + MXLog.warning("Couldn't find timeline item.") + return + } + + guard let eventTimelineItem = timelineItem as? EventBasedTimelineItemProtocol else { + fatalError("Only events can have send info.") + } + + 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)) + } else if let authenticityMessage = eventTimelineItem.properties.encryptionAuthenticity?.message { + displayAlert(.encryptionAuthenticity(authenticityMessage)) + } + } + + private func slashCommand(message: String) -> SlashCommand? { + for command in SlashCommand.allCases where message.starts(with: command.rawValue) { + return command + } + return nil + } + + private func handleJoinCommand(message: String) { + guard let alias = String(message.dropFirst(SlashCommand.join.rawValue.count)) + .components(separatedBy: .whitespacesAndNewlines) + .first, + let urlString = try? matrixToRoomAliasPermalink(roomAlias: alias), + let url = URL(string: urlString) else { + return + } + state.openURL?(url) + } + + private func sendCurrentMessage(_ message: String, html: String?, mode: ComposerMode, intentionalMentions: IntentionalMentions) async { + guard !message.isEmpty else { + fatalError("This message should never be empty") + } + + actionsSubject.send(.composer(action: .clear)) + + switch mode { + case .reply(let itemId, _, _): + await timelineController.sendMessage(message, + html: html, + inReplyTo: itemId, + intentionalMentions: intentionalMentions) + case .edit(let originalItemId): + await timelineController.edit(originalItemId, + message: message, + html: html, + intentionalMentions: intentionalMentions) + case .default: + switch slashCommand(message: message) { + case .join: + handleJoinCommand(message: message) + case .none: + await timelineController.sendMessage(message, + html: html, + intentionalMentions: intentionalMentions) + } + case .recordVoiceMessage, .previewVoiceMessage: + fatalError("invalid composer mode.") + } + + scrollToBottom() + } + + private func trackComposerMode(_ mode: ComposerMode) { + var isEdit = false + var isReply = false + switch mode { + case .edit: + isEdit = true + case .reply: + isReply = true + default: + break + } + + analyticsService.trackComposer(inThread: false, isEditing: isEdit, isReply: isReply, startsThread: nil) + } + + // MARK: - Timeline Item Building + + private func buildTimelineViews(timelineItems: [RoomTimelineItemProtocol], isSwitchingTimelines: Bool = false) { + var timelineItemsDictionary = OrderedDictionary() + + timelineItems.filter { $0 is RedactedRoomTimelineItem }.forEach { timelineItem in + // Stops the audio player when a voice message is redacted. + guard let playerState = mediaPlayerProvider.playerState(for: .timelineItemIdentifier(timelineItem.id)) else { + return + } + + Task { @MainActor in + playerState.detachAudioPlayer() + mediaPlayerProvider.unregister(audioPlayerState: playerState) + } + } + + let itemsGroupedByTimelineDisplayStyle = timelineItems.chunked { current, next in + canGroupItem(timelineItem: current, with: next) + } + + for itemGroup in itemsGroupedByTimelineDisplayStyle { + guard !itemGroup.isEmpty else { + MXLog.error("Found empty item group") + continue + } + + if itemGroup.count == 1 { + if let firstItem = itemGroup.first { + timelineItemsDictionary.updateValue(updateViewState(item: firstItem, groupStyle: .single), + forKey: firstItem.id.timelineID) + } + } else { + for (index, item) in itemGroup.enumerated() { + if index == 0 { + timelineItemsDictionary.updateValue(updateViewState(item: item, groupStyle: state.isPinnedEventsTimeline ? .single : .first), + forKey: item.id.timelineID) + } else if index == itemGroup.count - 1 { + timelineItemsDictionary.updateValue(updateViewState(item: item, groupStyle: state.isPinnedEventsTimeline ? .single : .last), + forKey: item.id.timelineID) + } else { + timelineItemsDictionary.updateValue(updateViewState(item: item, groupStyle: state.isPinnedEventsTimeline ? .single : .middle), + forKey: item.id.timelineID) + } + } + } + } + + if isSwitchingTimelines { + state.timelineViewState.isSwitchingTimelines = true + } + + state.timelineViewState.itemsDictionary = timelineItemsDictionary + } + + private func updateViewState(item: RoomTimelineItemProtocol, groupStyle: TimelineGroupStyle) -> RoomTimelineItemViewState { + if let timelineItemViewState = state.timelineViewState.itemsDictionary[item.id.timelineID] { + timelineItemViewState.groupStyle = groupStyle + timelineItemViewState.type = .init(item: item) + return timelineItemViewState + } else { + return RoomTimelineItemViewState(item: item, groupStyle: groupStyle) + } + } + + private func canGroupItem(timelineItem: RoomTimelineItemProtocol, with otherTimelineItem: RoomTimelineItemProtocol) -> Bool { + if timelineItem is CollapsibleTimelineItem || otherTimelineItem is CollapsibleTimelineItem { + return false + } + + guard let eventTimelineItem = timelineItem as? EventBasedTimelineItemProtocol, + let otherEventTimelineItem = otherTimelineItem as? EventBasedTimelineItemProtocol else { + return false + } + + // State events aren't rendered as messages so shouldn't be grouped. + if eventTimelineItem is StateRoomTimelineItem || otherEventTimelineItem is StateRoomTimelineItem { + return false + } + + // can be improved by adding a date threshold + return eventTimelineItem.properties.reactions.isEmpty && eventTimelineItem.sender == otherEventTimelineItem.sender + } + + // MARK: - Direct chats logics + + private func showInviteAlert() { + userIndicatorController.alertInfo = .init(id: .init(), + title: L10n.screenRoomInviteAgainAlertTitle, + message: L10n.screenRoomInviteAgainAlertMessage, + primaryButton: .init(title: L10n.actionInvite, action: { [weak self] in self?.inviteOtherDMUserBack() }), + secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) + } + + private let inviteLoadingIndicatorID = UUID().uuidString + + private func inviteOtherDMUserBack() { + guard roomProxy.isUserAloneInDirectRoom else { + userIndicatorController.alertInfo = .init(id: .init(), title: L10n.commonError) + return + } + + Task { + userIndicatorController.submitIndicator(.init(id: inviteLoadingIndicatorID, type: .toast, title: L10n.commonLoading)) + defer { + userIndicatorController.retractIndicatorWithId(inviteLoadingIndicatorID) + } + + guard + let members = await roomProxy.members(), + members.count == 2, + let otherPerson = members.first(where: { $0.userID != roomProxy.ownUserID && $0.membership == .leave }) + else { + userIndicatorController.alertInfo = .init(id: .init(), title: L10n.commonError) + return + } + + switch await roomProxy.invite(userID: otherPerson.userID) { + case .success: + break + case .failure: + userIndicatorController.alertInfo = .init(id: .init(), + title: L10n.commonUnableToInviteTitle, + message: L10n.commonUnableToInviteMessage) + } + } + } + + // MARK: - Reactions + + private func displayReactionSummary(for itemID: TimelineItemIdentifier, selectedKey: String) { + guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID), + let eventTimelineItem = timelineItem as? EventBasedTimelineItemProtocol else { + return + } + + state.bindings.reactionSummaryInfo = .init(reactions: eventTimelineItem.properties.reactions, selectedKey: selectedKey) + } + + // MARK: - Read Receipts + + private func displayReadReceipts(for itemID: TimelineItemIdentifier) { + guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID), + let eventTimelineItem = timelineItem as? EventBasedTimelineItemProtocol else { + return + } + + state.bindings.readReceiptsSummaryInfo = .init(orderedReceipts: eventTimelineItem.properties.orderedReadReceipts, id: eventTimelineItem.id) + } + + // MARK: - Message forwarding + + private func forwardMessage(itemID: TimelineItemIdentifier) async { + guard let content = await timelineController.messageEventContent(for: itemID) else { return } + actionsSubject.send(.displayMessageForwarding(forwardingItem: .init(id: itemID, roomID: roomProxy.id, content: content))) + } + + // MARK: - User Indicators + + private func showFocusLoadingIndicator() { + userIndicatorController.submitIndicator(UserIndicator(id: Constants.focusTimelineToastIndicatorID, + type: .toast(progress: .indeterminate), + title: L10n.commonLoading, + persistent: true)) + } + + private func hideFocusLoadingIndicator() { + userIndicatorController.retractIndicatorWithId(Constants.focusTimelineToastIndicatorID) + } + + private func displayAlert(_ type: RoomScreenAlertInfoType) { + switch type { + case .audioRecodingPermissionError: + state.bindings.alertInfo = .init(id: type, + title: L10n.dialogPermissionMicrophoneTitleIos(InfoPlistReader.main.bundleDisplayName), + message: L10n.dialogPermissionMicrophoneDescriptionIos, + primaryButton: .init(title: L10n.commonSettings, action: { [weak self] in self?.appMediator.openAppSettings() }), + secondaryButton: .init(title: L10n.actionNotNow, role: .cancel, action: nil)) + case .pollEndConfirmation(let pollStartID): + state.bindings.alertInfo = .init(id: type, + title: L10n.actionEndPoll, + message: L10n.commonPollEndConfirmation, + primaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil), + secondaryButton: .init(title: L10n.actionOk, action: { self.timelineInteractionHandler.endPoll(pollStartID: pollStartID) })) + case .sendingFailed: + state.bindings.alertInfo = .init(id: type, + title: L10n.commonSendingFailed, + primaryButton: .init(title: L10n.actionOk, action: nil)) + case .encryptionAuthenticity(let message): + state.bindings.alertInfo = .init(id: type, + title: message, + primaryButton: .init(title: L10n.actionOk, action: nil)) + } + } + + private func displayErrorToast(_ title: String) { + userIndicatorController.submitIndicator(UserIndicator(id: Constants.toastErrorID, + type: .toast, + title: title, + iconName: "xmark")) + } +} + +private extension RoomProxyProtocol { + /// Checks if the other person left the room in a direct chat + var isUserAloneInDirectRoom: Bool { + isDirect && activeMembersCount == 1 + } +} + +// MARK: - Mocks + +extension TimelineViewModel { + static let mock = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")), + focussedEventID: nil, + timelineController: MockRoomTimelineController(), + mediaProvider: MockMediaProvider(), + mediaPlayerProvider: MediaPlayerProviderMock(), + voiceMessageMediaManager: VoiceMessageMediaManagerMock(), + userIndicatorController: ServiceLocator.shared.userIndicatorController, + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) + + static let pinnedEventsTimelineMock = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")), + focussedEventID: nil, + timelineController: MockRoomTimelineController(timelineKind: .pinned), + mediaProvider: MockMediaProvider(), + mediaPlayerProvider: MediaPlayerProviderMock(), + voiceMessageMediaManager: VoiceMessageMediaManagerMock(), + userIndicatorController: ServiceLocator.shared.userIndicatorController, + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) +} + +private struct TimelineContextKey: EnvironmentKey { + @MainActor static let defaultValue: TimelineViewModel.Context? = nil +} + +private struct FocussedEventID: EnvironmentKey { + static let defaultValue: String? = nil +} + +extension EnvironmentValues { + /// Used to access and inject the room context without observing it + var timelineContext: TimelineViewModel.Context? { + get { self[TimelineContextKey.self] } + set { self[TimelineContextKey.self] = newValue } + } + + /// An event ID which will be non-nil when a timeline item should show as focussed. + var focussedEventID: String? { + get { self[FocussedEventID.self] } + set { self[FocussedEventID.self] = newValue } + } +} + +private enum SlashCommand: String, CaseIterable { + case join = "/join " +} diff --git a/ElementX/Sources/Screens/Timeline/TimelineViewModelProtocol.swift b/ElementX/Sources/Screens/Timeline/TimelineViewModelProtocol.swift new file mode 100644 index 0000000000..be707daa2f --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/TimelineViewModelProtocol.swift @@ -0,0 +1,20 @@ +// +// 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 Foundation +import SwiftUI + +@MainActor +protocol TimelineViewModelProtocol { + var actions: AnyPublisher { get } + var context: TimelineViewModel.Context { get } + func process(composerAction: ComposerToolbarViewModelAction) + /// Updates the timeline to show and highlight the item with the corresponding event ID. + func focusOnEvent(eventID: String) async + func stop() +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/ItemMenu/TimelineItemMacContextMenu.swift b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMacContextMenu.swift similarity index 83% rename from ElementX/Sources/Screens/RoomScreen/View/ItemMenu/TimelineItemMacContextMenu.swift rename to ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMacContextMenu.swift index 1a5477bc59..f97ae80116 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/ItemMenu/TimelineItemMacContextMenu.swift +++ b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMacContextMenu.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenu.swift b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenu.swift new file mode 100644 index 0000000000..8f65d0837a --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenu.swift @@ -0,0 +1,326 @@ +// +// 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 TimelineItemMenu: View { + @EnvironmentObject private var context: TimelineViewModel.Context + @Environment(\.dismiss) private var dismiss + + @State private var reactionsFrame = CGRect.zero + + let item: EventBasedTimelineItemProtocol + let actions: TimelineItemMenuActions + private let feedbackGenerator = UIImpactFeedbackGenerator(style: .heavy) + + var body: some View { + VStack(spacing: 8) { + messagePreview + .padding(.horizontal, 16) + .padding(.top, 32.0) + .padding(.bottom, 4.0) + .frame(idealWidth: 300.0) + + Divider() + .background(Color.compound.bgSubtlePrimary) + + ScrollView { + VStack(alignment: .leading, spacing: 0.0) { + if !actions.reactions.isEmpty { + reactionsSection + .padding(.bottom, 8.0) + + Divider() + .background(Color.compound.bgSubtlePrimary) + } + + if !actions.actions.isEmpty { + viewsForActions(actions.actions) + + Divider() + .background(Color.compound.bgSubtlePrimary) + } + + viewsForActions(actions.debugActions) + } + } + } + .accessibilityIdentifier(A11yIdentifiers.roomScreen.timelineItemActionMenu) + .presentationPage() + .presentationDetents([.medium, .large]) + .presentationBackground(Color.compound.bgCanvasDefault) + .presentationDragIndicator(.visible) + } + + private var messagePreview: some View { + VStack(alignment: .leading, spacing: 20) { + HStack(alignment: .top, spacing: 0.0) { + LoadableAvatarImage(url: item.sender.avatarURL, + name: item.sender.displayName, + contentID: item.sender.id, + avatarSize: .user(on: .timeline), + mediaProvider: context.mediaProvider) + .accessibilityHidden(true) + + Spacer(minLength: 8.0) + + VStack(alignment: .leading, spacing: 0) { + Text(item.sender.displayName ?? item.sender.id) + .font(.compound.bodySMSemibold) + .foregroundColor(.compound.textPrimary) + .textSelection(.enabled) + + Text(item.timelineMenuDescription) + .font(.compound.bodyMD) + .foregroundColor(.compound.textSecondary) + .lineLimit(1) + } + .frame(maxWidth: .infinity, alignment: .leading) + + Spacer(minLength: 16.0) + + Text(item.timestamp) + .font(.compound.bodyXS) + .foregroundColor(.compound.textSecondary) + } + .accessibilityElement(children: .combine) + + if case let .sendingFailed(.verifiedUser(failure)) = item.properties.deliveryStatus { + Divider() + .padding(.horizontal, -16) + + VerifiedUserSendFailureView(failure: failure, + members: context.viewState.members, + ownUserID: context.viewState.ownUserID) { + send(.itemSendInfoTapped(itemID: item.id)) + } + .padding(.bottom, 8) + } else if let authenticity = item.properties.encryptionAuthenticity { + Label(authenticity.message, icon: authenticity.icon, iconSize: .small, relativeTo: .compound.bodySMSemibold) + .font(.compound.bodySMSemibold) + .foregroundStyle(authenticity.foregroundStyle) + } + } + } + + 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)) + } + } 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) + } + + private func reactionButton(for emoji: String) -> some View { + Button { + feedbackGenerator.impactOccurred() + dismiss() + context.send(viewAction: .toggleReaction(key: emoji, itemID: item.id)) + } label: { + Text(emoji) + .font(.compound.headingLG) + .padding(8) + .background(Circle() + .foregroundColor(reactionBackgroundColor(for: emoji))) + .frame(maxWidth: .infinity, alignment: .leading) + } + } + + private func reactionBackgroundColor(for emoji: String) -> Color { + if let reaction = item.properties.reactions.first(where: { $0.key == emoji }), + reaction.isHighlighted { + return .compound.bgActionPrimaryRest + } else { + return .clear + } + } + + private func viewsForActions(_ actions: [TimelineItemMenuAction]) -> some View { + ForEach(actions, id: \.self) { action in + Button(role: action.isDestructive ? .destructive : nil) { + send(action) + } label: { + action.label + .labelStyle(.menuSheet) + } + } + } + + private func send(_ action: TimelineItemMenuAction) { + send(.handleTimelineItemMenuAction(itemID: item.id, action: action)) + } + + private func send(_ action: TimelineViewAction) { + dismiss() + // Otherwise we might get errors that a sheet is already presented + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + context.send(viewAction: action) + } + } +} + +private struct VerifiedUserSendFailureView: View { + let failure: TimelineItemSendFailure.VerifiedUser + let action: () -> Void + + private let memberDisplayName: String + private let isYou: Bool + + init(failure: TimelineItemSendFailure.VerifiedUser, + members: [String: RoomMemberState], + ownUserID: String, + action: @escaping () -> Void) { + self.failure = failure + self.action = action + + let userIDs = failure.affectedUserIDs + memberDisplayName = userIDs.first.map { members[$0]?.displayName ?? $0 } ?? "" + isYou = ownUserID == userIDs.first + } + + var title: String { + switch failure { + case .hasUnsignedDevice: + isYou ? L10n.screenTimelineItemMenuSendFailureYouUnsignedDevice : L10n.screenTimelineItemMenuSendFailureUnsignedDevice(memberDisplayName) + case .changedIdentity: + L10n.screenTimelineItemMenuSendFailureChangedIdentity(memberDisplayName) + } + } + + var body: some View { + Button(action: action) { + HStack(spacing: 8) { + Label(title, icon: \.error, iconSize: .small, relativeTo: .compound.bodySMSemibold) + .font(.compound.bodySMSemibold) + .foregroundStyle(.compound.textCriticalPrimary) + .frame(maxWidth: .infinity, alignment: .leading) + ListRowAccessory.navigationLink + } + } + } +} + +private extension EncryptionAuthenticity { + var foregroundStyle: SwiftUI.Color { + switch color { + case .red: .compound.textCriticalPrimary + case .gray: .compound.textSecondary + } + } +} + +private extension View { + /// Uses the old page style modal so that on iPadOS 18 the presentation detents have no effect. + @ViewBuilder func presentationPage() -> some View { + // Tchap: don't check for iOS 18 while not using Xcode 16 +// if #available(iOS 18.0, *) { +// presentationSizing(.page) +// } else { + self +// } + } +} + +// MARK: - Previews + +struct TimelineItemMenu_Previews: PreviewProvider, TestablePreview { + 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: [ + "@alice:matrix.org" + ])))) + static let (unsignedDevicesItem, _) = makeItem(deliveryStatus: .sendingFailed(.verifiedUser(.hasUnsignedDevice(devices: [ + "@alice:matrix.org": ["DEVICE1", "DEVICE2"] + ])))) + static let (ownUnsignedDevicesItem, _) = makeItem(deliveryStatus: .sendingFailed(.verifiedUser(.hasUnsignedDevice(devices: [ + RoomMemberProxyMock.mockMe.userID: ["DEVICE1"] + ])))) + + static var previews: some View { + TimelineItemMenu(item: item, actions: actions) + .environmentObject(viewModel.context) + .previewDisplayName("Normal") + + TimelineItemMenu(item: item, actions: actions) + .environmentObject(viewModel.context) + .environment(\._accessibilityShowButtonShapes, true) + .previewDisplayName("Button shapes") + + TimelineItemMenu(item: backupItem, actions: actions) + .environmentObject(viewModel.context) + .previewDisplayName("Authenticity") + + TimelineItemMenu(item: unsignedItem, actions: actions) + .environmentObject(viewModel.context) + .previewDisplayName("Unsigned") + + TimelineItemMenu(item: unencryptedItem, actions: actions) + .environmentObject(viewModel.context) + .previewDisplayName("Unencrypted") + + TimelineItemMenu(item: unknownFailureItem, actions: actions) + .environmentObject(viewModel.context) + .previewDisplayName("Unknown failure") + + TimelineItemMenu(item: unsignedDevicesItem, actions: actions) + .environmentObject(viewModel.context) + .previewDisplayName("Unsigned Devices") + + TimelineItemMenu(item: ownUnsignedDevicesItem, actions: actions) + .environmentObject(viewModel.context) + .previewDisplayName("Own Unsigned Devices") + + TimelineItemMenu(item: identityChangedItem, actions: actions) + .environmentObject(viewModel.context) + .previewDisplayName("Identity Changed") + } + + 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]) else { + return nil + } + + if let authenticity { + item.properties.encryptionAuthenticity = authenticity + } + + if let deliveryStatus { + item.properties.deliveryStatus = deliveryStatus + } + + return (item, actions) + } +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/ItemMenu/TimelineItemMenuAction.swift b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift similarity index 85% rename from ElementX/Sources/Screens/RoomScreen/View/ItemMenu/TimelineItemMenuAction.swift rename to ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift index 4fa340a75a..0ef3a10d35 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/ItemMenu/TimelineItemMenuAction.swift +++ b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SFSafeSymbols @@ -63,6 +54,7 @@ enum TimelineItemMenuAction: Identifiable, Hashable { case endPoll(pollStartID: String) case pin case unpin + case viewInRoomTimeline var id: Self { self } @@ -89,7 +81,7 @@ enum TimelineItemMenuAction: Identifiable, Hashable { /// Whether the action should be shown for a redacted item. var canAppearInRedacted: Bool { switch self { - case .viewSource: + case .viewSource, .unpin, .viewInRoomTimeline: return true default: return false @@ -106,6 +98,15 @@ enum TimelineItemMenuAction: Identifiable, Hashable { } } + var canAppearInPinnedEventsTimeline: Bool { + switch self { + case .viewInRoomTimeline, .pin, .unpin, .forward: + return true + default: + return false + } + } + /// The action's label. @ViewBuilder var label: some View { @@ -139,6 +140,8 @@ enum TimelineItemMenuAction: Identifiable, Hashable { Label(L10n.actionPin, icon: \.pin) case .unpin: Label(L10n.actionUnpin, icon: \.unpin) + case .viewInRoomTimeline: + Label(L10n.actionViewInTimeline, icon: \.visibilityOn) } } } diff --git a/ElementX/Sources/Screens/RoomScreen/View/ItemMenu/TimelineItemMenuActionProvider.swift b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift similarity index 81% rename from ElementX/Sources/Screens/RoomScreen/View/ItemMenu/TimelineItemMenuActionProvider.swift rename to ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift index 45f5028a45..f3b79fb5df 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/ItemMenu/TimelineItemMenuActionProvider.swift +++ b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -24,6 +15,7 @@ struct TimelineItemMenuActionProvider { let pinnedEventIDs: Set let isDM: Bool let isViewSourceEnabled: Bool + let isPinnedEventsTimeline: Bool // swiftlint:disable:next cyclomatic_complexity func makeActions() -> TimelineItemMenuActions? { @@ -66,14 +58,14 @@ 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.isEditable { actions.append(.edit) } + + if canCurrentUserPin, let eventID = item.id.eventID { + actions.append(pinnedEventIDs.contains(eventID) ? .unpin : .pin) + } if item.isCopyable { actions.append(.copy) @@ -102,8 +94,13 @@ struct TimelineItemMenuActionProvider { if item.isRedacted { actions = actions.filter(\.canAppearInRedacted) } + + if isPinnedEventsTimeline { + actions.insert(.viewInRoomTimeline, at: 0) + actions = actions.filter(\.canAppearInPinnedEventsTimeline) + } - return .init(isReactable: item.isReactable, actions: actions, debugActions: debugActions) + return .init(isReactable: isPinnedEventsTimeline ? false : item.isReactable, actions: actions, debugActions: debugActions) } private func canRedactItem(_ item: EventBasedTimelineItemProtocol) -> Bool { diff --git a/ElementX/Sources/Screens/RoomScreen/View/Polls/PollOptionView.swift b/ElementX/Sources/Screens/Timeline/View/Polls/PollOptionView.swift similarity index 88% rename from ElementX/Sources/Screens/RoomScreen/View/Polls/PollOptionView.swift rename to ElementX/Sources/Screens/Timeline/View/Polls/PollOptionView.swift index de9a78cbce..1b6f91d50a 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Polls/PollOptionView.swift +++ b/ElementX/Sources/Screens/Timeline/View/Polls/PollOptionView.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/Screens/Timeline/View/Polls/PollView.swift b/ElementX/Sources/Screens/Timeline/View/Polls/PollView.swift new file mode 100644 index 0000000000..a58ed54ce4 --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/Polls/PollView.swift @@ -0,0 +1,195 @@ +// +// Copyright 2023, 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Compound +import SwiftUI + +enum PollViewAction { + case selectOption(optionID: String) + case edit + case end +} + +enum PollViewState { + case preview + case full(isEditable: Bool) + + var isPreview: Bool { + switch self { + case .preview: + return true + case .full: + return false + } + } + + var isEditable: Bool { + switch self { + case .preview: + return false + case .full(let isEditable): + return isEditable + } + } +} + +struct PollView: View { + private let feedbackGenerator = UIImpactFeedbackGenerator(style: .heavy) + + let poll: Poll + let state: PollViewState + let actionHandler: (PollViewAction) -> Void + + var body: some View { + if state.isPreview { + questionView + } else { + VStack(alignment: .leading, spacing: 16) { + questionView + optionsView + summaryView + toolbarView + } + .frame(maxWidth: 450) + } + } + + // MARK: - Private + + private var questionView: some View { + HStack(alignment: .top, spacing: 12) { + CompoundIcon(poll.hasEnded ? \.pollsEnd : \.polls, + size: .custom(22), + relativeTo: .compound.bodyLGSemibold) + .accessibilityHidden(true) + + Text(poll.question) + .multilineTextAlignment(.leading) + .font(.compound.bodyLGSemibold) + } + } + + private var optionsView: some View { + ForEach(poll.options, id: \.id) { option in + Button { + guard !option.isSelected else { return } + actionHandler(.selectOption(optionID: option.id)) + feedbackGenerator.impactOccurred() + } label: { + PollOptionView(pollOption: option, + showVotes: showVotes, + isFinalResult: poll.hasEnded) + .foregroundColor(progressBarColor(for: option)) + } + .disabled(poll.hasEnded) + } + } + + @ViewBuilder + private var summaryView: some View { + if let summaryText = poll.summaryText { + Text(summaryText) + .font(.compound.bodySM) + .scaledPadding(.leading, showVotes ? 0 : 32) + .foregroundColor(.compound.textSecondary) + .frame(maxWidth: .infinity, alignment: showVotes ? .trailing : .leading) + } + } + + @ViewBuilder + private var toolbarView: some View { + if !poll.hasEnded, poll.createdByAccountOwner { + Button { + toolbarAction() + } label: { + Text(state.isEditable ? L10n.actionEditPoll : L10n.actionEndPoll) + .lineLimit(2, reservesSpace: false) + .font(.compound.bodyLGSemibold) + .foregroundColor(.compound.textOnSolidPrimary) + .padding(.horizontal, 24) + .padding(.vertical, 10) + .frame(maxWidth: .infinity) + .background { + Capsule() + .foregroundColor(.compound.bgActionPrimaryRest) + } + } + .padding(.top, 8) + } + } + + private func toolbarAction() { + if state.isEditable { + actionHandler(.edit) + } else { + actionHandler(.end) + } + } + + private func progressBarColor(for option: Poll.Option) -> Color { + if poll.hasEnded { + return option.isWinning ? .compound.textActionAccent : .compound.textDisabled + } else { + return .compound.textPrimary + } + } + + private var showVotes: Bool { + poll.hasEnded || poll.kind == .disclosed + } +} + +private extension Poll { + var summaryText: String? { + guard !hasEnded else { + return options.first.map { + L10n.commonPollTotalVotes($0.allVotes) + } + } + + switch kind { + case .disclosed: + return options.first.map { + L10n.commonPollTotalVotes($0.allVotes) + } + case .undisclosed: + return L10n.commonPollUndisclosedText + } + } +} + +struct PollView_Previews: PreviewProvider, TestablePreview { + static var previews: some View { + PollView(poll: .disclosed(), state: .full(isEditable: false)) { _ in } + .padding() + .previewDisplayName("Disclosed") + + PollView(poll: .undisclosed(), state: .full(isEditable: false)) { _ in } + .padding() + .previewDisplayName("Undisclosed") + + PollView(poll: .endedDisclosed, state: .full(isEditable: false)) { _ in } + .padding() + .previewDisplayName("Ended, Disclosed") + + PollView(poll: .endedUndisclosed, state: .full(isEditable: false)) { _ in } + .padding() + .previewDisplayName("Ended, Undisclosed") + + PollView(poll: .disclosed(createdByAccountOwner: true), state: .full(isEditable: true)) { _ in } + .padding() + .previewDisplayName("Creator, disclosed") + + PollView(poll: .emptyDisclosed, state: .full(isEditable: true)) { _ in } + .padding() + .previewDisplayName("Creator, no votes") + + PollView(poll: .emptyDisclosed, state: .preview) { _ in } + .padding() + .previewDisplayName("Preview") + } +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/ReadReceipts/ReadReceiptCell.swift b/ElementX/Sources/Screens/Timeline/View/ReadReceipts/ReadReceiptCell.swift similarity index 75% rename from ElementX/Sources/Screens/RoomScreen/View/ReadReceipts/ReadReceiptCell.swift rename to ElementX/Sources/Screens/Timeline/View/ReadReceipts/ReadReceiptCell.swift index a920bf5221..033e3c084e 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/ReadReceipts/ReadReceiptCell.swift +++ b/ElementX/Sources/Screens/Timeline/View/ReadReceipts/ReadReceiptCell.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -19,7 +10,7 @@ import SwiftUI struct ReadReceiptCell: View { let readReceipt: ReadReceipt let memberState: RoomMemberState? - let imageProvider: ImageProviderProtocol? + let mediaProvider: MediaProviderProtocol? private var title: String { memberState?.displayName ?? readReceipt.userID @@ -38,7 +29,7 @@ struct ReadReceiptCell: View { name: memberState?.displayName, contentID: readReceipt.userID, avatarSize: .user(on: .readReceiptSheet), - imageProvider: imageProvider) + mediaProvider: mediaProvider) VStack(alignment: .leading, spacing: 0) { HStack(spacing: 12) { Text(title) @@ -70,18 +61,18 @@ struct ReadReceiptCell_Previews: PreviewProvider, TestablePreview { formattedTimestamp: "10:00"), memberState: .init(displayName: "Test", avatarURL: nil), - imageProvider: MockMediaProvider()) + mediaProvider: MockMediaProvider()) .previewDisplayName("No Image") ReadReceiptCell(readReceipt: .init(userID: "@test:matrix.org", formattedTimestamp: "10:00"), memberState: .init(displayName: "Test", avatarURL: URL.documentsDirectory), - imageProvider: MockMediaProvider()) + mediaProvider: MockMediaProvider()) .previewDisplayName("With Image") ReadReceiptCell(readReceipt: .init(userID: "@test:matrix.org", formattedTimestamp: "10:00"), memberState: nil, - imageProvider: MockMediaProvider()) + mediaProvider: MockMediaProvider()) .previewDisplayName("Loading Member") } } diff --git a/ElementX/Sources/Screens/Timeline/View/ReadReceipts/ReadReceiptsSummaryView.swift b/ElementX/Sources/Screens/Timeline/View/ReadReceipts/ReadReceiptsSummaryView.swift new file mode 100644 index 0000000000..50294df598 --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/ReadReceipts/ReadReceiptsSummaryView.swift @@ -0,0 +1,70 @@ +// +// 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 + +struct ReadReceiptsSummaryView: View { + let orderedReadReceipts: [ReadReceipt] + @EnvironmentObject private var context: TimelineViewModel.Context + + var body: some View { + VStack(alignment: .leading, spacing: 16) { + Text(L10n.commonSeenBy) + .font(.compound.bodyLGSemibold) + .foregroundColor(.compound.textPrimary) + .padding(.horizontal, 16) + ScrollView { + LazyVStack(spacing: 0) { + ForEach(orderedReadReceipts) { receipt in + ReadReceiptCell(readReceipt: receipt, + memberState: context.viewState.members[receipt.userID], + mediaProvider: context.mediaProvider) + } + } + } + } + .padding(.top, 24) + .presentationDetents([.medium, .large]) + .presentationBackground(Color.compound.bgCanvasDefault) + .presentationDragIndicator(.visible) + } +} + +struct ReadReceiptsSummaryView_Previews: PreviewProvider, TestablePreview { + static let viewModel = { + let members: [RoomMemberProxyMock] = [ + .mockAlice, + .mockBob, + .mockCharlie, + .mockDan + ] + let roomProxyMock = JoinedRoomProxyMock(.init(name: "Room", members: members)) + let mock = TimelineViewModel(roomProxy: roomProxyMock, + timelineController: MockRoomTimelineController(), + mediaProvider: MockMediaProvider(), + mediaPlayerProvider: MediaPlayerProviderMock(), + voiceMessageMediaManager: VoiceMessageMediaManagerMock(), + userIndicatorController: UserIndicatorControllerMock(), + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) + return mock + }() + + static let orderedReadReceipts: [ReadReceipt] = [ + .init(userID: "@alice:matrix.org", formattedTimestamp: "10:00"), + .init(userID: "@bob:matrix.org", formattedTimestamp: "9:30"), + .init(userID: "@charlie:matrix.org", formattedTimestamp: "9:00"), + .init(userID: "@dan:matrix.org", formattedTimestamp: "8:30"), + .init(userID: "@loading:matrix.org", formattedTimestamp: "Long time ago") + ] + + static var previews: some View { + ReadReceiptsSummaryView(orderedReadReceipts: orderedReadReceipts) + .environmentObject(viewModel.context) + } +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Replies/TimelineReplyView.swift b/ElementX/Sources/Screens/Timeline/View/Replies/TimelineReplyView.swift similarity index 95% rename from ElementX/Sources/Screens/RoomScreen/View/Replies/TimelineReplyView.swift rename to ElementX/Sources/Screens/Timeline/View/Replies/TimelineReplyView.swift index 7b670b2800..0a1b88bd8c 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Replies/TimelineReplyView.swift +++ b/ElementX/Sources/Screens/Timeline/View/Replies/TimelineReplyView.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -122,7 +113,7 @@ struct TimelineReplyView: View { let cornerRadii: Double } - @EnvironmentObject private var context: RoomScreenViewModel.Context + @EnvironmentObject private var context: TimelineViewModel.Context @ScaledMetric private var imageContainerSize = 36.0 let sender: TimelineItemSender @@ -164,7 +155,7 @@ struct TimelineReplyView: View { LoadableImage(mediaSource: mediaSource, size: .init(width: imageContainerSize, height: imageContainerSize), - imageProvider: context.imageProvider) { + mediaProvider: context.mediaProvider) { Image(systemName: "photo") .padding(4.0) } @@ -216,7 +207,7 @@ struct TimelineReplyView: View { } struct TimelineReplyView_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock + static let viewModel = TimelineViewModel.mock static let attributedStringWithMention = { var attributedString = AttributedString("To be replaced") @@ -326,7 +317,7 @@ struct TimelineReplyView_Previews: PreviewProvider, TestablePreview { .padding() .environmentObject(viewModel.context) // Allow member names to load. Reduce precission as the `imageSource` randomly renders slightly differently - .snapshot(delay: 0.2, precision: 0.98) + .snapshotPreferences(delay: 0.2, precision: 0.98) .previewLayout(.sizeThatFits) } } diff --git a/ElementX/Sources/Screens/RoomScreen/View/Style/LongPressWithFeedback.swift b/ElementX/Sources/Screens/Timeline/View/Style/LongPressWithFeedback.swift similarity index 86% rename from ElementX/Sources/Screens/RoomScreen/View/Style/LongPressWithFeedback.swift rename to ElementX/Sources/Screens/Timeline/View/Style/LongPressWithFeedback.swift index 6c68f1d3ee..357960c313 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Style/LongPressWithFeedback.swift +++ b/ElementX/Sources/Screens/Timeline/View/Style/LongPressWithFeedback.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -67,7 +58,7 @@ struct LongPressWithFeedback_Previews: PreviewProvider, TestablePreview { static var previews: some View { Preview() } struct Preview: View { - private let viewModel = RoomScreenViewModel.mock + private let viewModel = TimelineViewModel.mock @State private var isPresentingSheet = false var body: some View { diff --git a/ElementX/Sources/Screens/Timeline/View/Style/SwipeToReplyView.swift b/ElementX/Sources/Screens/Timeline/View/Style/SwipeToReplyView.swift new file mode 100644 index 0000000000..fb4520621e --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/Style/SwipeToReplyView.swift @@ -0,0 +1,34 @@ +// +// Copyright 2023, 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Compound +import SwiftUI + +struct SwipeToReplyView: View { + let timelineItem: RoomTimelineItemProtocol + + var body: some View { + CompoundIcon(\.reply) + .foregroundColor(.compound.iconPrimary) + .accessibilityHidden(true) + } +} + +struct SwipeToReplyView_Previews: PreviewProvider, TestablePreview { + static let timelineItem = TextRoomTimelineItem(id: .init(timelineID: ""), + timestamp: "", + isOutgoing: true, + isEditable: true, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: ""), + content: .init(body: "")) + + static var previews: some View { + SwipeToReplyView(timelineItem: timelineItem) + } +} diff --git a/ElementX/Sources/Screens/Timeline/View/Style/ThreadDecorator.swift b/ElementX/Sources/Screens/Timeline/View/Style/ThreadDecorator.swift new file mode 100644 index 0000000000..65ba0abbfa --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/Style/ThreadDecorator.swift @@ -0,0 +1,30 @@ +// +// 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 + +import Compound + +struct ThreadDecorator: View { + var body: some View { + Label { + Text(L10n.commonThread) + .foregroundColor(.compound.textPrimary) + .font(.compound.bodyXS) + } icon: { + CompoundIcon(\.threads, size: .xSmall, relativeTo: .compound.bodyXS) + .foregroundColor(.compound.iconSecondary) + } + .labelStyle(.custom(spacing: 4)) + } +} + +struct ThreadDecorator_Previews: PreviewProvider, TestablePreview { + static var previews: some View { + ThreadDecorator() + } +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Style/TimelineBubbleLayout.swift b/ElementX/Sources/Screens/Timeline/View/Style/TimelineBubbleLayout.swift similarity index 87% rename from ElementX/Sources/Screens/RoomScreen/View/Style/TimelineBubbleLayout.swift rename to ElementX/Sources/Screens/Timeline/View/Style/TimelineBubbleLayout.swift index cf90458d07..fef868e63a 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Style/TimelineBubbleLayout.swift +++ b/ElementX/Sources/Screens/Timeline/View/Style/TimelineBubbleLayout.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemAccessibilityModifier.swift b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemAccessibilityModifier.swift new file mode 100644 index 0000000000..76f375c626 --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemAccessibilityModifier.swift @@ -0,0 +1,49 @@ +// +// 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 + +private struct TimelineItemAccessibilityModifier: ViewModifier { + let timelineItem: RoomTimelineItemProtocol + let action: () -> Void + + @ViewBuilder + func body(content: Content) -> some View { + switch timelineItem { + case is PollRoomTimelineItem, is VoiceMessageRoomTimelineItem: + content + .accessibilityActions { + Button(L10n.commonMessageActions) { + action() + } + } + case let timelineItem as EventBasedTimelineItemProtocol: + content + .accessibilityRepresentation { + VStack(spacing: 8) { + Text(timelineItem.sender.displayName ?? timelineItem.sender.id) + content + } + } + .accessibilityElement(children: .combine) + .accessibilityActions { + Button(L10n.commonMessageActions) { + action() + } + } + default: + content + .accessibilityElement(children: .combine) + } + } +} + +extension View { + func timelineItemAccessibility(_ timelineItem: RoomTimelineItemProtocol, action: @escaping () -> Void) -> some View { + modifier(TimelineItemAccessibilityModifier(timelineItem: timelineItem, action: action)) + } +} diff --git a/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift new file mode 100644 index 0000000000..32b33c57a8 --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift @@ -0,0 +1,709 @@ +// +// 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 TimelineItemBubbledStylerView: View { + @EnvironmentObject private var context: TimelineViewModel.Context + @Environment(\.timelineGroupStyle) private var timelineGroupStyle + @Environment(\.focussedEventID) private var focussedEventID + + let timelineItem: EventBasedTimelineItemProtocol + let adjustedDeliveryStatus: TimelineItemDeliveryStatus? + @ViewBuilder let content: () -> Content + + private var isEncryptedOneToOneRoom: Bool { context.viewState.isEncryptedOneToOneRoom } + private var isFocussed: Bool { focussedEventID != nil && timelineItem.id.eventID == focussedEventID } + private var isPinned: Bool { + guard !context.viewState.isPinnedEventsTimeline, + let eventID = timelineItem.id.eventID else { + return false + } + return context.viewState.pinnedEventIDs.contains(eventID) + } + + /// The base padding applied to bubbles on either side. + /// + /// **Note:** This is on top of the insets applied to the cells by the table view. + private let bubbleHorizontalPadding: CGFloat = 8 + /// Additional padding applied to outgoing bubbles when the avatar is shown + private var bubbleAvatarPadding: CGFloat { + guard !timelineItem.isOutgoing, !isEncryptedOneToOneRoom else { return 0 } + return 8 + } + + var body: some View { + ZStack(alignment: .trailingFirstTextBaseline) { + VStack(alignment: alignment, spacing: -12) { + if !timelineItem.isOutgoing, !isEncryptedOneToOneRoom { + header + .zIndex(1) + } + + VStack(alignment: alignment, spacing: 0) { + HStack(spacing: 0) { + if timelineItem.isOutgoing { + Spacer() + } + + messageBubbleWithReactions + } + .padding(timelineItem.isOutgoing ? .leading : .trailing, 48) // Additional padding to differentiate alignment. + + HStack(spacing: 0) { + if !timelineItem.isOutgoing { + Spacer() + } + TimelineItemStatusView(timelineItem: timelineItem, adjustedDeliveryStatus: adjustedDeliveryStatus) + .environmentObject(context) + .padding(.top, 8) + .padding(.bottom, 3) + } + } + .padding(.horizontal, bubbleHorizontalPadding) + .padding(.leading, bubbleAvatarPadding) + } + } + .padding(EdgeInsets(top: 1, leading: 8, bottom: 1, trailing: 8)) + .highlightedTimelineItem(isFocussed) + } + + @ViewBuilder + private var header: some View { + if shouldShowSenderDetails { + HStack(alignment: .top, spacing: 4) { + TimelineSenderAvatarView(timelineItem: timelineItem) + HStack(alignment: .center, spacing: 4) { + Text(timelineItem.sender.displayName ?? timelineItem.sender.id) + .font(.compound.bodySMSemibold) + .foregroundColor(.compound.decorativeColor(for: timelineItem.sender.id).text) + + if timelineItem.sender.displayName != nil, timelineItem.sender.isDisplayNameAmbiguous { + Text(timelineItem.sender.id) + .font(.compound.bodyXS) + .foregroundColor(.compound.textSecondary) + } + } + .lineLimit(1) + .scaledPadding(.vertical, 3) + } + // sender info are read inside the `TimelineAccessibilityModifier` + .accessibilityHidden(true) + .onTapGesture { + context.send(viewAction: .tappedOnSenderDetails(userID: timelineItem.sender.id)) + } + .padding(.top, 8) + } + } + + private var messageBubbleWithReactions: some View { + // Figma overlaps reactions by 3 + VStack(alignment: alignment, spacing: -3) { + messageBubbleWithActions + .timelineItemAccessibility(timelineItem) { + context.send(viewAction: .displayTimelineItemMenu(itemID: timelineItem.id)) + } + + // Do not display reactions in the pinned events timeline + if !context.viewState.isPinnedEventsTimeline, + !timelineItem.properties.reactions.isEmpty { + TimelineReactionsView(context: context, + itemID: timelineItem.id, + reactions: timelineItem.properties.reactions, + isLayoutRTL: timelineItem.isOutgoing) + // Workaround to stop the message long press stealing the touch from the reaction buttons + .onTapGesture { } + } + } + } + + 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)) + } + .swipeRightAction { + SwipeToReplyView(timelineItem: timelineItem) + } shouldStartAction: { + timelineItem.canBeRepliedTo + } action: { + let isThread = (timelineItem as? EventBasedMessageTimelineItemProtocol)?.isThreaded ?? false + context.send(viewAction: .handleTimelineItemMenuAction(itemID: timelineItem.id, action: .reply(isThread: isThread))) + } + .contextMenu { + let provider = TimelineItemMenuActionProvider(timelineItem: timelineItem, + canCurrentUserRedactSelf: context.viewState.canCurrentUserRedactSelf, + canCurrentUserRedactOthers: context.viewState.canCurrentUserRedactOthers, + canCurrentUserPin: context.viewState.canCurrentUserPin, + pinnedEventIDs: context.viewState.pinnedEventIDs, + isDM: context.viewState.isEncryptedOneToOneRoom, + isViewSourceEnabled: context.viewState.isViewSourceEnabled, + isPinnedEventsTimeline: context.viewState.isPinnedEventsTimeline) + TimelineItemMacContextMenu(item: timelineItem, actionProvider: provider) { action in + context.send(viewAction: .handleTimelineItemMenuAction(itemID: timelineItem.id, action: action)) + } + } + .pinnedIndicator(isPinned: isPinned, isOutgoing: timelineItem.isOutgoing) + .padding(.top, messageBubbleTopPadding) + } + + var messageBubble: some View { + contentWithReply + .timelineItemSendInfo(timelineItem: timelineItem, adjustedDeliveryStatus: adjustedDeliveryStatus, context: context) + .bubbleStyle(insets: timelineItem.bubbleInsets, + color: timelineItem.bubbleBackgroundColor, + corners: roundedCorners) + } + + @ViewBuilder + var contentWithReply: some View { + TimelineBubbleLayout(spacing: 8) { + if let messageTimelineItem = timelineItem as? EventBasedMessageTimelineItemProtocol { + if messageTimelineItem.isThreaded { + ThreadDecorator() + .padding(.leading, 4) + .layoutPriority(TimelineBubbleLayout.Priority.regularText) + } + + if let replyDetails = messageTimelineItem.replyDetails { + // The rendered reply bubble with a greedy width. The custom layout prevents + // the infinite width from increasing the overall width of the view. + + TimelineReplyView(placement: .timeline, timelineItemReplyDetails: replyDetails) + .fixedSize(horizontal: false, vertical: true) + .padding(4.0) + .frame(maxWidth: .infinity, alignment: .leading) + .background(Color.compound.bgCanvasDefault) + .cornerRadius(8) + .layoutPriority(TimelineBubbleLayout.Priority.visibleQuote) + .onTapGesture { + context.send(viewAction: .focusOnEventID(replyDetails.eventID)) + } + + // Add a fixed width reply bubble that is used for layout calculations but won't be rendered. + TimelineReplyView(placement: .timeline, timelineItemReplyDetails: replyDetails) + .fixedSize(horizontal: false, vertical: true) + .padding(4.0) + .layoutPriority(TimelineBubbleLayout.Priority.hiddenQuote) + .hidden() + } + } + + content() + .layoutPriority(TimelineBubbleLayout.Priority.regularText) + .cornerRadius(timelineItem.contentCornerRadius) + } + } + + private var messageBubbleTopPadding: CGFloat { + guard timelineItem.isOutgoing || isEncryptedOneToOneRoom else { return 0 } + return timelineGroupStyle == .single || timelineGroupStyle == .first ? 8 : 0 + } + + private var alignment: HorizontalAlignment { + timelineItem.isOutgoing ? .trailing : .leading + } + + private var roundedCorners: UIRectCorner { + switch timelineGroupStyle { + case .single: + return .allCorners + case .first: + if timelineItem.isOutgoing { + return [.topLeft, .topRight, .bottomLeft] + } else { + return [.topLeft, .topRight, .bottomRight] + } + case .middle: + return timelineItem.isOutgoing ? [.topLeft, .bottomLeft] : [.topRight, .bottomRight] + case .last: + if timelineItem.isOutgoing { + return [.topLeft, .bottomLeft, .bottomRight] + } else { + return [.topRight, .bottomLeft, .bottomRight] + } + } + } + + private var shouldShowSenderDetails: Bool { + timelineGroupStyle.shouldShowSenderDetails + } +} + +private extension View { + func bubbleStyle(insets: EdgeInsets, color: Color? = nil, cornerRadius: CGFloat = 12, corners: UIRectCorner) -> some View { + padding(insets) + .background(color) + .cornerRadius(cornerRadius, corners: corners) + } +} + +private extension EventBasedTimelineItemProtocol { + var bubbleBackgroundColor: Color? { + let defaultColor: Color = isOutgoing ? .compound._bgBubbleOutgoing : .compound._bgBubbleIncoming + + switch self { + case let self as EventBasedMessageTimelineItemProtocol: + switch self { + case is ImageRoomTimelineItem, is VideoRoomTimelineItem: + // In case a reply detail or a thread decorator is present we render the color and the padding + return self.replyDetails != nil || self.isThreaded ? defaultColor : nil + default: + return defaultColor + } + case is StickerRoomTimelineItem: + return nil + default: + return defaultColor + } + } + + /// The insets for the full bubble content. + /// Padding affecting just the "send info" should be added inside `TimelineItemSendInfoView` + var bubbleInsets: EdgeInsets { + let defaultInsets: EdgeInsets = .init(around: 8) + + switch self { + case is StickerRoomTimelineItem: + return .zero + case is PollRoomTimelineItem: + return .init(top: 12, leading: 12, bottom: 4, trailing: 12) + case let self as EventBasedMessageTimelineItemProtocol: + switch self { + // In case a reply detail or a thread decorator is present we render the color and the padding + case is ImageRoomTimelineItem, + is VideoRoomTimelineItem: + return self.replyDetails != nil || + self.isThreaded ? defaultInsets : .zero + case let locationTimelineItem as LocationRoomTimelineItem: + return locationTimelineItem.content.geoURI == nil || + self.replyDetails != nil || + self.isThreaded ? defaultInsets : .zero + default: + return defaultInsets + } + default: + return defaultInsets + } + } + + var contentCornerRadius: CGFloat { + guard let message = self as? EventBasedMessageTimelineItemProtocol else { return .zero } + + switch message { + case is ImageRoomTimelineItem, is VideoRoomTimelineItem, is LocationRoomTimelineItem: + return message.replyDetails != nil || message.isThreaded ? 8 : .zero + default: + return .zero + } + } +} + +private extension EdgeInsets { + init(around: CGFloat) { + self.init(top: around, leading: around, bottom: around, trailing: around) + } + + static var zero: Self = .init(around: 0) +} + +private struct PinnedIndicatorViewModifier: ViewModifier { + let isPinned: Bool + let isOutgoing: Bool + + func body(content: Content) -> some View { + if isPinned { + HStack(alignment: .top, spacing: 8) { + if isOutgoing { + pinnedIndicator + } + content + .layoutPriority(1) + if !isOutgoing { + pinnedIndicator + } + } + } else { + content + } + } + + private var pinnedIndicator: some View { + CompoundIcon(\.pinSolid, size: .xSmall, relativeTo: .compound.bodyMD) + .foregroundStyle(Color.compound.iconTertiary) + } +} + +private extension View { + func pinnedIndicator(isPinned: Bool, isOutgoing: Bool) -> some View { + modifier(PinnedIndicatorViewModifier(isPinned: isPinned, isOutgoing: isOutgoing)) + } +} + +// MARK: - Previews + +struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview { + static let viewModel = TimelineViewModel.mock + static let viewModelWithPins: TimelineViewModel = { + var settings = AppSettings() + settings.pinningEnabled = true + let roomProxy = JoinedRoomProxyMock(.init(name: "Preview Room", pinnedEventIDs: [""])) + return TimelineViewModel(roomProxy: roomProxy, + focussedEventID: nil, + timelineController: MockRoomTimelineController(), + mediaProvider: MockMediaProvider(), + mediaPlayerProvider: MediaPlayerProviderMock(), + voiceMessageMediaManager: VoiceMessageMediaManagerMock(), + userIndicatorController: ServiceLocator.shared.userIndicatorController, + appMediator: AppMediatorMock.default, + appSettings: settings, + analyticsService: ServiceLocator.shared.analytics) + }() + + static var previews: some View { + mockTimeline + .previewDisplayName("Mock Timeline") + mockTimeline + .environment(\.layoutDirection, .rightToLeft) + .previewDisplayName("Mock Timeline RTL") + replies + .previewDisplayName("Replies") + threads + .previewDisplayName("Thread decorator") + encryptionAuthenticity + .previewDisplayName("Encryption Indicators") + pinned + .previewDisplayName("Pinned messages") + .snapshotPreferences(delay: 1.0) + } + + // These always include a reply + static var threads: some View { + ScrollView { + RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(timelineID: ""), + timestamp: "10:42", + isOutgoing: true, + isEditable: false, + canBeRepliedTo: true, + isThreaded: true, + sender: .init(id: "whoever"), + content: .init(body: "A long message that should be on multiple lines."), + replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), + eventID: "123", + eventContent: .message(.text(.init(body: "Short"))))), + groupStyle: .single)) + + AudioRoomTimelineView(timelineItem: .init(id: .init(timelineID: ""), + timestamp: "10:42", + isOutgoing: true, + isEditable: false, + canBeRepliedTo: true, + isThreaded: true, + sender: .init(id: ""), + content: .init(body: "audio.ogg", + duration: 100, + waveform: EstimatedWaveform.mockWaveform, + source: nil, + contentType: nil), + replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), + eventID: "123", + eventContent: .message(.text(.init(body: "Short")))))) + + FileRoomTimelineView(timelineItem: .init(id: .init(timelineID: ""), + timestamp: "10:42", + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: true, + sender: .init(id: ""), + content: .init(body: "File", + source: nil, + thumbnailSource: nil, + contentType: nil), + replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), + eventID: "123", + eventContent: .message(.text(.init(body: "Short")))))) + ImageRoomTimelineView(timelineItem: .init(id: .init(timelineID: ""), + timestamp: "10:42", + isOutgoing: true, + isEditable: true, + canBeRepliedTo: true, + isThreaded: true, + sender: .init(id: ""), + content: .init(body: "Some image", source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"), thumbnailSource: nil), + replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), + eventID: "123", + eventContent: .message(.text(.init(body: "Short")))))) + LocationRoomTimelineView(timelineItem: .init(id: .random, + timestamp: "Now", + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: true, + sender: .init(id: "Bob"), + content: .init(body: "Fallback geo uri description", + geoURI: .init(latitude: 41.902782, + longitude: 12.496366), + description: "Location description description description description description description description description"), + replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), + eventID: "123", + eventContent: .message(.text(.init(body: "Short")))))) + LocationRoomTimelineView(timelineItem: .init(id: .random, + timestamp: "Now", + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: true, + sender: .init(id: "Bob"), + content: .init(body: "Fallback geo uri description", + geoURI: .init(latitude: 41.902782, longitude: 12.496366), description: nil), + replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), + eventID: "123", + eventContent: .message(.text(.init(body: "Short")))))) + + VoiceMessageRoomTimelineView(timelineItem: .init(id: .init(timelineID: ""), + timestamp: "10:42", + isOutgoing: true, + isEditable: false, + canBeRepliedTo: true, + isThreaded: true, + sender: .init(id: ""), + content: .init(body: "audio.ogg", + duration: 100, + waveform: EstimatedWaveform.mockWaveform, + source: nil, + contentType: nil), + replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), + eventID: "123", + eventContent: .message(.text(.init(body: "Short"))))), + playerState: AudioPlayerState(id: .timelineItemIdentifier(.random), + title: L10n.commonVoiceMessage, + duration: 10, + waveform: EstimatedWaveform.mockWaveform)) + } + .environmentObject(viewModel.context) + } + + static var mockTimeline: some View { + ScrollView { + VStack(alignment: .leading, spacing: 0) { + ForEach(viewModel.state.timelineViewState.itemViewStates) { viewState in + RoomTimelineItemView(viewState: viewState) + } + } + } + .environmentObject(viewModel.context) + } + + static var replies: some View { + VStack(spacing: 0) { + RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(timelineID: ""), + timestamp: "10:42", + isOutgoing: true, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "whoever"), + content: .init(body: "A long message that should be on multiple lines."), + replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), + eventID: "123", + eventContent: .message(.text(.init(body: "Short"))))), + groupStyle: .single)) + + RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(timelineID: ""), + timestamp: "10:42", + isOutgoing: true, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "whoever"), + content: .init(body: "Short message"), + replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), + eventID: "123", + eventContent: .message(.text(.init(body: "A long message that should be on more than 2 lines and so will be clipped by the layout."))))), + groupStyle: .single)) + } + .environmentObject(viewModel.context) + } + + static var encryptionAuthenticity: some View { + VStack(spacing: 0) { + RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(timelineID: ""), + timestamp: "10:42", + isOutgoing: true, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "whoever"), + content: .init(body: "A long message that should be on multiple lines."), + properties: RoomTimelineItemProperties(encryptionAuthenticity: .unsignedDevice(color: .red))), + groupStyle: .single)) + + RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(timelineID: ""), + timestamp: "10:42", + isOutgoing: true, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "whoever"), + content: .init(body: "A long message that should be on multiple lines."), + properties: RoomTimelineItemProperties(isEdited: true, + encryptionAuthenticity: .unsignedDevice(color: .red))), + groupStyle: .single)) + + RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(timelineID: ""), + timestamp: "10:42", + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "whoever"), + content: .init(body: "Short message"), + properties: RoomTimelineItemProperties(encryptionAuthenticity: .unknownDevice(color: .red))), + groupStyle: .first)) + + RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(timelineID: ""), + timestamp: "10:42", + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "whoever"), + content: .init(body: "Message goes Here"), + properties: RoomTimelineItemProperties(encryptionAuthenticity: .notGuaranteed(color: .gray))), + groupStyle: .last)) + + ImageRoomTimelineView(timelineItem: ImageRoomTimelineItem(id: .random, + timestamp: "Now", + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "Bob"), + content: .init(body: "Some other image", source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"), thumbnailSource: nil), + + properties: RoomTimelineItemProperties(encryptionAuthenticity: .notGuaranteed(color: .gray)))) + + VoiceMessageRoomTimelineView(timelineItem: .init(id: .init(timelineID: ""), + timestamp: "10:42", + isOutgoing: true, + isEditable: false, + canBeRepliedTo: true, + isThreaded: true, + sender: .init(id: ""), + content: .init(body: "audio.ogg", + duration: 100, + waveform: EstimatedWaveform.mockWaveform, + source: nil, + contentType: nil), + properties: RoomTimelineItemProperties(encryptionAuthenticity: .notGuaranteed(color: .gray))), + playerState: AudioPlayerState(id: .timelineItemIdentifier(.random), + title: L10n.commonVoiceMessage, + duration: 10, + waveform: EstimatedWaveform.mockWaveform)) + } + .environmentObject(viewModel.context) + } + + static var pinned: some View { + ScrollView { + RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(timelineID: "", eventID: ""), + timestamp: "10:42", + isOutgoing: true, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "whoever"), + content: .init(body: "A long message that should be on multiple lines."), + replyDetails: nil), + groupStyle: .single)) + + AudioRoomTimelineView(timelineItem: .init(id: .init(timelineID: "", eventID: ""), + timestamp: "10:42", + isOutgoing: true, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: ""), + content: .init(body: "audio.ogg", + duration: 100, + waveform: EstimatedWaveform.mockWaveform, + source: nil, + contentType: nil), + replyDetails: nil)) + + FileRoomTimelineView(timelineItem: .init(id: .init(timelineID: "", eventID: ""), + timestamp: "10:42", + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: ""), + content: .init(body: "File", + source: nil, + thumbnailSource: nil, + contentType: nil), + replyDetails: nil)) + ImageRoomTimelineView(timelineItem: .init(id: .init(timelineID: "", eventID: ""), + timestamp: "10:42", + isOutgoing: true, + isEditable: true, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: ""), + content: .init(body: "Some image", source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"), thumbnailSource: nil), + replyDetails: nil)) + LocationRoomTimelineView(timelineItem: .init(id: .init(timelineID: "", eventID: ""), + timestamp: "Now", + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "Bob"), + content: .init(body: "Fallback geo uri description", + geoURI: .init(latitude: 41.902782, + longitude: 12.496366), + description: "Location description description description description description description description description"), + replyDetails: nil)) + LocationRoomTimelineView(timelineItem: .init(id: .init(timelineID: "", eventID: ""), + timestamp: "Now", + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "Bob"), + content: .init(body: "Fallback geo uri description", + geoURI: .init(latitude: 41.902782, longitude: 12.496366), description: nil), + replyDetails: nil)) + + VoiceMessageRoomTimelineView(timelineItem: .init(id: .init(timelineID: "", eventID: ""), + timestamp: "10:42", + isOutgoing: true, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: ""), + content: .init(body: "audio.ogg", + duration: 100, + waveform: EstimatedWaveform.mockWaveform, + source: nil, + contentType: nil), + replyDetails: nil), + playerState: AudioPlayerState(id: .timelineItemIdentifier(.random), + title: L10n.commonVoiceMessage, + duration: 10, + waveform: EstimatedWaveform.mockWaveform)) + } + .environmentObject(viewModelWithPins.context) + } +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Style/TimelineItemSendInfoLabel.swift b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemSendInfoLabel.swift similarity index 90% rename from ElementX/Sources/Screens/RoomScreen/View/Style/TimelineItemSendInfoLabel.swift rename to ElementX/Sources/Screens/Timeline/View/Style/TimelineItemSendInfoLabel.swift index d12b7d37fb..04e5544a43 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Style/TimelineItemSendInfoLabel.swift +++ b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemSendInfoLabel.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -21,7 +12,7 @@ extension View { /// Adds the send info (timestamp along indicators for edits and delivery/encryption issues) for the given timeline item to this view. func timelineItemSendInfo(timelineItem: EventBasedTimelineItemProtocol, adjustedDeliveryStatus: TimelineItemDeliveryStatus?, - context: RoomScreenViewModel.Context) -> some View { + context: TimelineViewModel.Context) -> some View { modifier(TimelineItemSendInfoModifier(sendInfo: .init(timelineItem: timelineItem, adjustedDeliveryStatus: adjustedDeliveryStatus), context: context)) @@ -31,7 +22,7 @@ extension View { /// Adds the send info to a view with the correct layout. private struct TimelineItemSendInfoModifier: ViewModifier { let sendInfo: TimelineItemSendInfo - let context: RoomScreenViewModel.Context + let context: TimelineViewModel.Context var layout: AnyLayout { switch sendInfo.layoutType { @@ -150,7 +141,7 @@ private extension TimelineItemSendInfo { itemID = timelineItem.id localizedString = timelineItem.localizedSendInfo - status = if adjustedDeliveryStatus == .sendingFailed { + status = if case .sendingFailed = adjustedDeliveryStatus { .sendingFailed } else if let authenticity = timelineItem.properties.encryptionAuthenticity { .encryptionAuthenticity(authenticity) diff --git a/ElementX/Sources/Screens/Timeline/View/Style/TimelineStyle.swift b/ElementX/Sources/Screens/Timeline/View/Style/TimelineStyle.swift new file mode 100644 index 0000000000..b8294a041c --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/Style/TimelineStyle.swift @@ -0,0 +1,38 @@ +// +// 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 SwiftUI + +enum TimelineGroupStyle: Hashable { + case single + case first + case middle + case last + + var shouldShowSenderDetails: Bool { + switch self { + case .single, .first: + return true + default: + return false + } + } +} + +// MARK: - Environment + +private struct TimelineGroupStyleKey: EnvironmentKey { + static let defaultValue = TimelineGroupStyle.single +} + +extension EnvironmentValues { + var timelineGroupStyle: TimelineGroupStyle { + get { self[TimelineGroupStyleKey.self] } + set { self[TimelineGroupStyleKey.self] = newValue } + } +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Style/TimelineStyler.swift b/ElementX/Sources/Screens/Timeline/View/Style/TimelineStyler.swift similarity index 92% rename from ElementX/Sources/Screens/RoomScreen/View/Style/TimelineStyler.swift rename to ElementX/Sources/Screens/Timeline/View/Style/TimelineStyler.swift index a9216b508a..4d09e9216b 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Style/TimelineStyler.swift +++ b/ElementX/Sources/Screens/Timeline/View/Style/TimelineStyler.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -35,11 +26,13 @@ struct TimelineStyler: View { var body: some View { mainContent .onChange(of: timelineItem.properties.deliveryStatus) { newStatus in - if newStatus == .sendingFailed { + if case .sendingFailed = newStatus { guard task == nil else { return } task = Task { + // Add a short delay so that an immediate failure when retrying + // shows as sending for long enough to be visible to the user. try? await Task.sleep(for: .milliseconds(700)) if !Task.isCancelled { adjustedDeliveryStatus = newStatus @@ -62,7 +55,7 @@ struct TimelineStyler: View { } struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock + static let viewModel = TimelineViewModel.mock static let base = TextRoomTimelineItem(id: .random, timestamp: "Now", @@ -101,7 +94,7 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview { static let failed: TextRoomTimelineItem = { var result = base - result.properties.deliveryStatus = .sendingFailed + result.properties.deliveryStatus = .sendingFailed(.unknown) return result }() diff --git a/ElementX/Sources/Screens/RoomScreen/View/Supplementary/ReactionsSummaryView.swift b/ElementX/Sources/Screens/Timeline/View/Supplementary/ReactionsSummaryView.swift similarity index 83% rename from ElementX/Sources/Screens/RoomScreen/View/Supplementary/ReactionsSummaryView.swift rename to ElementX/Sources/Screens/Timeline/View/Supplementary/ReactionsSummaryView.swift index 53fbfc0e34..5f535f7063 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Supplementary/ReactionsSummaryView.swift +++ b/ElementX/Sources/Screens/Timeline/View/Supplementary/ReactionsSummaryView.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -19,7 +10,7 @@ import SwiftUI struct ReactionsSummaryView: View { let reactions: [AggregatedReaction] let members: [String: RoomMemberState] - let imageProvider: ImageProviderProtocol? + let mediaProvider: MediaProviderProtocol? @State var selectedReactionKey: String @@ -64,7 +55,7 @@ struct ReactionsSummaryView: View { ScrollView { VStack(alignment: .leading, spacing: 8) { ForEach(reaction.senders) { sender in - ReactionSummarySenderView(sender: sender, member: members[sender.id], imageProvider: imageProvider) + ReactionSummarySenderView(sender: sender, member: members[sender.id], mediaProvider: mediaProvider) .padding(.horizontal, 16) } } @@ -110,7 +101,7 @@ private struct ReactionSummaryButton: View { private struct ReactionSummarySenderView: View { var sender: ReactionSender var member: RoomMemberState? - let imageProvider: ImageProviderProtocol? + let mediaProvider: MediaProviderProtocol? var displayName: String { member?.displayName ?? sender.id @@ -122,7 +113,7 @@ private struct ReactionSummarySenderView: View { name: displayName, contentID: sender.id, avatarSize: .user(on: .timeline), - imageProvider: imageProvider) + mediaProvider: mediaProvider) VStack(alignment: .leading, spacing: 0) { HStack(spacing: 8) { @@ -147,7 +138,7 @@ struct ReactionsSummaryView_Previews: PreviewProvider, TestablePreview { static var previews: some View { ReactionsSummaryView(reactions: AggregatedReaction.mockReactions, members: [:], - imageProvider: MockMediaProvider(), + mediaProvider: MockMediaProvider(), selectedReactionKey: AggregatedReaction.mockReactions[0].key) } } diff --git a/ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineDeliveryStatusView.swift b/ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineDeliveryStatusView.swift new file mode 100644 index 0000000000..3e9fdfa6bc --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineDeliveryStatusView.swift @@ -0,0 +1,51 @@ +// +// 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 TimelineDeliveryStatusView: View { + enum Status { + case sending + case sent + } + + let deliveryStatus: Status + + private var icon: CompoundIcon { + switch deliveryStatus { + case .sending: + return CompoundIcon(\.circle, size: .xSmall, relativeTo: .compound.bodyMD) + case .sent: + return CompoundIcon(\.checkCircle, size: .xSmall, relativeTo: .compound.bodyMD) + } + } + + var body: some View { + icon + .foregroundColor(.compound.iconSecondary) + .accessibilityLabel(accessibilityLabel) + } + + private var accessibilityLabel: String { + switch deliveryStatus { + case .sending: + return L10n.commonSending + case .sent: + return L10n.commonSent + } + } +} + +struct TimelineDeliveryStatusView_Previews: PreviewProvider, TestablePreview { + static var previews: some View { + VStack(spacing: 8) { + TimelineDeliveryStatusView(deliveryStatus: .sending) + TimelineDeliveryStatusView(deliveryStatus: .sent) + } + } +} diff --git a/ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineItemStatusView.swift b/ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineItemStatusView.swift new file mode 100644 index 0000000000..071351cc50 --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineItemStatusView.swift @@ -0,0 +1,56 @@ +// +// Copyright 2023, 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Compound +import SwiftUI + +struct TimelineItemStatusView: View { + let timelineItem: EventBasedTimelineItemProtocol + let adjustedDeliveryStatus: TimelineItemDeliveryStatus? + @EnvironmentObject private var context: TimelineViewModel.Context + + private var isLastOutgoingMessage: Bool { + timelineItem.isOutgoing && context.viewState.timelineViewState.timelineIDs.last == timelineItem.id.timelineID + } + + var body: some View { + mainContent + } + + @ViewBuilder + private var mainContent: some View { + if context.viewState.isPinnedEventsTimeline { + // Do not display any status when is a pinned events timeline + EmptyView() + } else if context.viewState.showReadReceipts, !timelineItem.properties.orderedReadReceipts.isEmpty { + readReceipts + } else { + deliveryStatusBadge + } + } + + @ViewBuilder + var deliveryStatusBadge: some View { + switch adjustedDeliveryStatus { + case .sending: + TimelineDeliveryStatusView(deliveryStatus: .sending) + case .sent, .none: + if isLastOutgoingMessage { + // We only display the sent icon for the latest outgoing message + TimelineDeliveryStatusView(deliveryStatus: .sent) + } + case .sendingFailed: + // Bubbles handle the case internally + EmptyView() + } + } + + var readReceipts: some View { + TimelineReadReceiptsView(timelineItem: timelineItem) + .environmentObject(context) + } +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Supplementary/TimelineReactionsView.swift b/ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineReactionsView.swift similarity index 88% rename from ElementX/Sources/Screens/RoomScreen/View/Supplementary/TimelineReactionsView.swift rename to ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineReactionsView.swift index f0b83a6f98..50b2459e15 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Supplementary/TimelineReactionsView.swift +++ b/ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineReactionsView.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -22,14 +13,14 @@ struct TimelineReactionsView: View { private let feedbackGenerator = UIImpactFeedbackGenerator(style: .heavy) @Environment(\.layoutDirection) private var layoutDirection: LayoutDirection - let context: RoomScreenViewModel.Context + let context: TimelineViewModel.Context let itemID: TimelineItemIdentifier let reactions: [AggregatedReaction] let isLayoutRTL: Bool private var collapsed: Binding - init(context: RoomScreenViewModel.Context, + init(context: TimelineViewModel.Context, itemID: TimelineItemIdentifier, reactions: [AggregatedReaction], isLayoutRTL: Bool = false) { @@ -204,20 +195,20 @@ struct TimelineReactionAddMoreButtonLabel: View { struct TimelineReactionViewPreviewsContainer: View { var body: some View { VStack(spacing: 8) { - TimelineReactionsView(context: RoomScreenViewModel.mock.context, + TimelineReactionsView(context: TimelineViewModel.mock.context, itemID: .init(timelineID: "1"), reactions: [AggregatedReaction.mockReactionWithLongText, AggregatedReaction.mockReactionWithLongTextRTL]) Divider() - TimelineReactionsView(context: RoomScreenViewModel.mock.context, + TimelineReactionsView(context: TimelineViewModel.mock.context, itemID: .init(timelineID: "2"), reactions: Array(AggregatedReaction.mockReactions.prefix(3))) Divider() - TimelineReactionsView(context: RoomScreenViewModel.mock.context, + TimelineReactionsView(context: TimelineViewModel.mock.context, itemID: .init(timelineID: "3"), reactions: AggregatedReaction.mockReactions) Divider() - TimelineReactionsView(context: RoomScreenViewModel.mock.context, + TimelineReactionsView(context: TimelineViewModel.mock.context, itemID: .init(timelineID: "4"), reactions: AggregatedReaction.mockReactions, isLayoutRTL: true) diff --git a/ElementX/Sources/Screens/RoomScreen/View/Supplementary/TimelineReadReceiptsView.swift b/ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineReadReceiptsView.swift similarity index 78% rename from ElementX/Sources/Screens/RoomScreen/View/Supplementary/TimelineReadReceiptsView.swift rename to ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineReadReceiptsView.swift index e4933ee342..16d63650b6 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Supplementary/TimelineReadReceiptsView.swift +++ b/ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineReadReceiptsView.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -19,7 +10,7 @@ import SwiftUI struct TimelineReadReceiptsView: View { let displayNumber = 3 let timelineItem: EventBasedTimelineItemProtocol - @EnvironmentObject private var context: RoomScreenViewModel.Context + @EnvironmentObject private var context: TimelineViewModel.Context var body: some View { HStack(spacing: 2) { @@ -31,7 +22,7 @@ struct TimelineReadReceiptsView: View { name: context.viewState.members[receipt.userID]?.displayName, contentID: receipt.userID, avatarSize: .user(on: .readReceipt), - imageProvider: context.imageProvider) + mediaProvider: context.mediaProvider) .overlay { RoundedRectangle(cornerRadius: .infinity) .stroke(Color.compound.bgCanvasDefault, lineWidth: 1) @@ -90,15 +81,15 @@ struct TimelineReadReceiptsView_Previews: PreviewProvider, TestablePreview { .mockMe ] - static let viewModel = RoomScreenViewModel(roomProxy: RoomProxyMock(.init(name: "Test", members: members)), - timelineController: MockRoomTimelineController(), - mediaProvider: MockMediaProvider(), - mediaPlayerProvider: MediaPlayerProviderMock(), - voiceMessageMediaManager: VoiceMessageMediaManagerMock(), - userIndicatorController: ServiceLocator.shared.userIndicatorController, - appMediator: AppMediatorMock.default, - appSettings: ServiceLocator.shared.settings, - analyticsService: ServiceLocator.shared.analytics) + static let viewModel = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Test", members: members)), + timelineController: MockRoomTimelineController(), + mediaProvider: MockMediaProvider(), + mediaPlayerProvider: MediaPlayerProviderMock(), + voiceMessageMediaManager: VoiceMessageMediaManagerMock(), + userIndicatorController: ServiceLocator.shared.userIndicatorController, + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) static let singleReceipt = [ReadReceipt(userID: RoomMemberProxyMock.mockAlice.userID, formattedTimestamp: "Now")] static let doubleReceipt = [ReadReceipt(userID: RoomMemberProxyMock.mockAlice.userID, formattedTimestamp: "Now"), diff --git a/ElementX/Sources/Screens/RoomScreen/View/TimelineItemDebugView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemDebugView.swift similarity index 84% rename from ElementX/Sources/Screens/RoomScreen/View/TimelineItemDebugView.swift rename to ElementX/Sources/Screens/Timeline/View/TimelineItemDebugView.swift index a26440c56f..c39d915396 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/TimelineItemDebugView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemDebugView.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/AudioRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/AudioRoomTimelineView.swift new file mode 100644 index 0000000000..a116d81efe --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/AudioRoomTimelineView.swift @@ -0,0 +1,46 @@ +// +// 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 +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) + } + } +} + +struct AudioRoomTimelineView_Previews: PreviewProvider, TestablePreview { + static let viewModel = TimelineViewModel.mock + + static var previews: some View { + body.environmentObject(viewModel.context) + } + + static var body: some View { + AudioRoomTimelineView(timelineItem: AudioRoomTimelineItem(id: .random, + timestamp: "Now", + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "Bob"), + content: .init(body: "audio.ogg", duration: 300, waveform: nil, source: nil, contentType: nil))) + } +} diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallInviteRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallInviteRoomTimelineView.swift new file mode 100644 index 0000000000..bb0406cb74 --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallInviteRoomTimelineView.swift @@ -0,0 +1,39 @@ +// +// 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 Foundation +import SwiftUI + +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() + } +} + +struct CallInviteRoomTimelineView_Previews: PreviewProvider, TestablePreview { + static let viewModel = TimelineViewModel.mock + + static var previews: some View { + body.environmentObject(viewModel.context) + } + + static var body: some View { + CallInviteRoomTimelineView(timelineItem: .init(id: .random, + timestamp: "Now", + isEditable: false, + canBeRepliedTo: false, + sender: .init(id: "Bob"))) + } +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/CallNotificationRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallNotificationRoomTimelineView.swift similarity index 75% rename from ElementX/Sources/Screens/RoomScreen/View/Timeline/CallNotificationRoomTimelineView.swift rename to ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallNotificationRoomTimelineView.swift index 4452c056e8..f3eefcd1af 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/CallNotificationRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallNotificationRoomTimelineView.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -19,7 +10,7 @@ import Foundation import SwiftUI struct CallNotificationRoomTimelineView: View { - @EnvironmentObject private var context: RoomScreenViewModel.Context + @EnvironmentObject private var context: TimelineViewModel.Context let timelineItem: CallNotificationRoomTimelineItem @@ -29,7 +20,7 @@ struct CallNotificationRoomTimelineView: View { name: timelineItem.sender.displayName ?? timelineItem.sender.id, contentID: timelineItem.sender.id, avatarSize: .user(on: .timeline), - imageProvider: context.imageProvider) + mediaProvider: context.mediaProvider) .accessibilityHidden(true) VStack(alignment: .leading, spacing: 0) { @@ -62,7 +53,7 @@ struct CallNotificationRoomTimelineView: View { } struct CallNotificationRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock + static let viewModel = TimelineViewModel.mock static var previews: some View { body.environmentObject(viewModel.context) diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/CollapsibleRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CollapsibleRoomTimelineView.swift similarity index 77% rename from ElementX/Sources/Screens/RoomScreen/View/Timeline/CollapsibleRoomTimelineView.swift rename to ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CollapsibleRoomTimelineView.swift index 3808d2eb30..9e03a81794 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/CollapsibleRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CollapsibleRoomTimelineView.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/EmoteRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/EmoteRoomTimelineView.swift similarity index 76% rename from ElementX/Sources/Screens/RoomScreen/View/Timeline/EmoteRoomTimelineView.swift rename to ElementX/Sources/Screens/Timeline/View/TimelineItemViews/EmoteRoomTimelineView.swift index 3d3057af50..77ce3bec5a 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/EmoteRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/EmoteRoomTimelineView.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -32,7 +23,7 @@ struct EmoteRoomTimelineView: View, TextBasedRoomTimelineViewProtocol { } struct EmoteRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock + static let viewModel = TimelineViewModel.mock static var previews: some View { body.environmentObject(viewModel.context) diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/EncryptedRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/EncryptedRoomTimelineView.swift similarity index 86% rename from ElementX/Sources/Screens/RoomScreen/View/Timeline/EncryptedRoomTimelineView.swift rename to ElementX/Sources/Screens/Timeline/View/TimelineItemViews/EncryptedRoomTimelineView.swift index c72d383c7e..5a69efe464 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/EncryptedRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/EncryptedRoomTimelineView.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -56,7 +47,7 @@ struct RoomTimelineViewLabelStyle: LabelStyle { } struct EncryptedRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock + static let viewModel = TimelineViewModel.mock static var previews: some View { body.environmentObject(viewModel.context) diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FileRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FileRoomTimelineView.swift new file mode 100644 index 0000000000..faf03fcf13 --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FileRoomTimelineView.swift @@ -0,0 +1,66 @@ +// +// 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 FileRoomTimelineView: View { + let timelineItem: FileRoomTimelineItem + + var body: some View { + TimelineStyler(timelineItem: timelineItem) { + Label { Text(timelineItem.body) } icon: { + CompoundIcon(\.document) + .foregroundColor(.compound.iconPrimary) + } + .labelStyle(RoomTimelineViewLabelStyle()) + .font(.compound.bodyLG) + .padding(.vertical, 8) + .padding(.horizontal, 6) + .accessibilityLabel(L10n.commonFile) + } + } +} + +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: .random, + timestamp: "Now", + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "Bob"), + content: .init(body: "document.pdf", source: nil, thumbnailSource: nil, contentType: nil))) + + FileRoomTimelineView(timelineItem: FileRoomTimelineItem(id: .random, + timestamp: "Now", + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "Bob"), + content: .init(body: "document.docx", source: nil, thumbnailSource: nil, contentType: nil))) + + FileRoomTimelineView(timelineItem: FileRoomTimelineItem(id: .random, + timestamp: "Now", + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "Bob"), + content: .init(body: "document.txt", source: nil, thumbnailSource: nil, contentType: nil))) + } + } +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/FormattedBodyText.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FormattedBodyText.swift similarity index 93% rename from ElementX/Sources/Screens/RoomScreen/View/Timeline/FormattedBodyText.swift rename to ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FormattedBodyText.swift index fe569b33a0..4790ee5ef6 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/FormattedBodyText.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FormattedBodyText.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -214,7 +205,7 @@ struct FormattedBodyText_Previews: PreviewProvider, TestablePreview { .padding() } .previewLayout(.sizeThatFits) - .snapshot(delay: 0.25) + .snapshotPreferences(delay: 0.25) } } @@ -224,7 +215,7 @@ private struct PreviewBubbleModifier: ViewModifier { .padding(8) .background(Color.compound._bgBubbleOutgoing) .cornerRadius(12) - .environmentObject(RoomScreenViewModel.mock.context) + .environmentObject(TimelineViewModel.mock.context) } } diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/HighlightedTimelineItemModifier.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/HighlightedTimelineItemModifier.swift new file mode 100644 index 0000000000..9b61793ff9 --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/HighlightedTimelineItemModifier.swift @@ -0,0 +1,109 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Compound +import SwiftUI + +extension View { + func highlightedTimelineItem(_ isHighlighted: Bool) -> some View { + modifier(HighlightedTimelineItemModifier(isHighlighted: isHighlighted)) + } +} + +private struct HighlightedTimelineItemModifier: ViewModifier { + let isHighlighted: Bool + + func body(content: Content) -> some View { + content + .padding(.top, isHighlighted ? 1 : 0) + .background { + if isHighlighted { + VStack(spacing: 0) { + Color.compound._bgBubbleHighlighted + LinearGradient(colors: [.compound._bgBubbleHighlighted, .clear], + startPoint: .top, + endPoint: .bottom) + .frame(maxHeight: 200) + .layoutPriority(1) + } + .overlay(alignment: .top) { + Color.compound.bgAccentRest + .frame(height: 1) + } + } + } + } +} + +// MARK: - Previews + +// swiftlint:disable line_length blanket_disable_command +struct HighlightedTimelineItemModifier_Previews: PreviewProvider, TestablePreview { + static var previews: some View { + ScrollView { + VStack(spacing: 16) { + Bubble(text: "Hello ๐Ÿ‘‹") + .highlightedTimelineItem(true) + + Bubble(text: "Not highlighted") + .highlightedTimelineItem(false) + + // swiftlint:disable line_length + Bubble(text: """ + Bacon ipsum dolor amet brisket bacon hamburger filet mignon ham hock, capicola meatloaf corned beef tongue. Ribeye filet mignon shoulder drumstick doner shank. Landjaeger shankle chislic brisket short loin pig. Frankfurter sirloin jerky bresaola tri-tip cow buffalo. Beef tongue shankle venison, sirloin boudin biltong ham hock corned beef. Sirloin shankle pork belly, strip steak pancetta brisket flank ribeye cow chislic. Pork ham landjaeger, pastrami beef sausage capicola meatball. + + Cow brisket bresaola, burgdoggen cupim turducken sirloin andouille shankle sausage jerky chicken pig. Tail capicola landjaeger frankfurter. Kevin pancetta brisket spare ribs, sausage chuck tail pork. Ground round boudin chuck tri-tip corned beef. Pork belly ham bresaola tail, pork chop meatloaf biltong filet mignon strip steak ribeye boudin shoulder frankfurter. + """, + isOutgoing: true) + .highlightedTimelineItem(true) + // swiftlint:enable line_length + } + } + .previewDisplayName("Layout") + } + + struct Bubble: View { + let text: String + var isOutgoing = false + + var body: some View { + Text(text) + .padding(10) + .background(isOutgoing ? .compound._bgBubbleOutgoing : .compound._bgBubbleIncoming, + in: RoundedRectangle(cornerRadius: 12)) + .padding(isOutgoing ? .leading : .trailing, 40) + .frame(maxWidth: .infinity, alignment: isOutgoing ? .trailing : .leading) + .padding(12) + } + } +} + +/// A preview that allows quick testing of the highlight appearance across various timeline scenarios. +struct HighlightedTimelineItemTimeline_Previews: PreviewProvider { + static let roomProxyMock = JoinedRoomProxyMock(.init(name: "Preview room")) + static let roomViewModel = RoomScreenViewModel.mock(roomProxyMock: roomProxyMock) + static let focussedEventID = "RoomTimelineItemFixtures.default.5" + static let timelineViewModel = TimelineViewModel(roomProxy: roomProxyMock, + focussedEventID: focussedEventID, + timelineController: MockRoomTimelineController(), + mediaProvider: MockMediaProvider(), + mediaPlayerProvider: MediaPlayerProviderMock(), + voiceMessageMediaManager: VoiceMessageMediaManagerMock(), + userIndicatorController: ServiceLocator.shared.userIndicatorController, + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) + + static var previews: some View { + NavigationStack { + RoomScreen(roomViewModel: roomViewModel, + timelineViewModel: timelineViewModel, + composerToolbar: ComposerToolbar.mock()) + } + .previewDisplayName("Timeline") + } +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/ImageRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift similarity index 85% rename from ElementX/Sources/Screens/RoomScreen/View/Timeline/ImageRoomTimelineView.swift rename to ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift index ffcf8e6cd3..b872a84973 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/ImageRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift @@ -1,31 +1,22 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation import SwiftUI struct ImageRoomTimelineView: View { - @EnvironmentObject private var context: RoomScreenViewModel.Context + @EnvironmentObject private var context: TimelineViewModel.Context let timelineItem: ImageRoomTimelineItem var body: some View { TimelineStyler(timelineItem: timelineItem) { LoadableImage(mediaSource: source, blurhash: timelineItem.content.blurhash, - imageProvider: context.imageProvider) { + mediaProvider: context.mediaProvider) { placeholder } .timelineMediaFrame(height: timelineItem.content.height, @@ -56,7 +47,7 @@ struct ImageRoomTimelineView: View { } struct ImageRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock + static let viewModel = TimelineViewModel.mock static var previews: some View { body diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/LocationRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/LocationRoomTimelineView.swift similarity index 89% rename from ElementX/Sources/Screens/RoomScreen/View/Timeline/LocationRoomTimelineView.swift rename to ElementX/Sources/Screens/Timeline/View/TimelineItemViews/LocationRoomTimelineView.swift index 3b70e530c3..8c32b487e3 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/LocationRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/LocationRoomTimelineView.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI @@ -81,7 +72,7 @@ private extension MapLibreStaticMapView { } struct LocationRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock + static let viewModel = TimelineViewModel.mock static var previews: some View { ScrollView { diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/NoticeRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/NoticeRoomTimelineView.swift similarity index 81% rename from ElementX/Sources/Screens/RoomScreen/View/Timeline/NoticeRoomTimelineView.swift rename to ElementX/Sources/Screens/Timeline/View/TimelineItemViews/NoticeRoomTimelineView.swift index 0232a638de..9fe8f8fbba 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/NoticeRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/NoticeRoomTimelineView.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -44,7 +35,7 @@ struct NoticeRoomTimelineView: View, TextBasedRoomTimelineViewProtocol { } struct NoticeRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock + static let viewModel = TimelineViewModel.mock static var previews: some View { body.environmentObject(viewModel.context) diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/PaginationIndicatorRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/PaginationIndicatorRoomTimelineView.swift new file mode 100644 index 0000000000..8c82a4b392 --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/PaginationIndicatorRoomTimelineView.swift @@ -0,0 +1,25 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import SwiftUI + +struct PaginationIndicatorRoomTimelineView: View { + let timelineItem: PaginationIndicatorRoomTimelineItem + + var body: some View { + ProgressView() + .frame(maxWidth: .infinity) + .padding(.top, 12) // Bottom spacing comes from the next item (date separator). + } +} + +struct PaginationIndicatorRoomTimelineView_Previews: PreviewProvider, TestablePreview { + static var previews: some View { + let item = PaginationIndicatorRoomTimelineItem(position: .start) + PaginationIndicatorRoomTimelineView(timelineItem: item) + } +} diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/PollRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/PollRoomTimelineView.swift new file mode 100644 index 0000000000..1f5a7d95d5 --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/PollRoomTimelineView.swift @@ -0,0 +1,85 @@ +// +// 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 + +struct PollRoomTimelineView: View { + let timelineItem: PollRoomTimelineItem + @EnvironmentObject private var context: TimelineViewModel.Context + + private var state: PollViewState { + if context.viewState.isPinnedEventsTimeline { + return .preview + } else { + return .full(isEditable: timelineItem.isEditable) + } + } + + var body: some View { + TimelineStyler(timelineItem: timelineItem) { + PollView(poll: poll, + state: state) { action in + switch action { + case .selectOption(let optionID): + guard let eventID, let option = poll.options.first(where: { $0.id == optionID }), !option.isSelected else { return } + context.send(viewAction: .handlePollAction(.selectOption(pollStartID: eventID, optionID: option.id))) + case .edit: + guard let eventID else { return } + context.send(viewAction: .handlePollAction(.edit(pollStartID: eventID, poll: poll))) + case .end: + guard let eventID else { return } + context.send(viewAction: .handlePollAction(.end(pollStartID: eventID))) + } + } + } + } + + // MARK: - Private + + private var poll: Poll { + timelineItem.poll + } + + private var eventID: String? { + timelineItem.id.eventID + } +} + +struct PollRoomTimelineView_Previews: PreviewProvider, TestablePreview { + static let viewModel = TimelineViewModel.mock + static let pinnedEventsTimelineViewModel = TimelineViewModel.pinnedEventsTimelineMock + + static var previews: some View { + PollRoomTimelineView(timelineItem: .mock(poll: .disclosed(), isOutgoing: false)) + .environmentObject(viewModel.context) + .previewDisplayName("Disclosed, Bubble") + + PollRoomTimelineView(timelineItem: .mock(poll: .undisclosed(), isOutgoing: false)) + .environmentObject(viewModel.context) + .previewDisplayName("Undisclosed, Bubble") + + PollRoomTimelineView(timelineItem: .mock(poll: .endedDisclosed)) + .environmentObject(viewModel.context) + .previewDisplayName("Ended, Disclosed, Bubble") + + PollRoomTimelineView(timelineItem: .mock(poll: .endedUndisclosed)) + .environmentObject(viewModel.context) + .previewDisplayName("Ended, Undisclosed, Bubble") + + PollRoomTimelineView(timelineItem: .mock(poll: .disclosed(createdByAccountOwner: true))) + .environmentObject(viewModel.context) + .previewDisplayName("Creator, disclosed, Bubble") + + PollRoomTimelineView(timelineItem: .mock(poll: .emptyDisclosed, isEditable: true)) + .environmentObject(viewModel.context) + .previewDisplayName("Creator, no votes, Bubble") + + PollRoomTimelineView(timelineItem: .mock(poll: .disclosed(), isEditable: true)) + .environmentObject(pinnedEventsTimelineViewModel.context) + .previewDisplayName("Preview") + } +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/ReadMarkerRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ReadMarkerRoomTimelineView.swift similarity index 81% rename from ElementX/Sources/Screens/RoomScreen/View/Timeline/ReadMarkerRoomTimelineView.swift rename to ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ReadMarkerRoomTimelineView.swift index ce552baba6..5c6f5c58bf 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/ReadMarkerRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ReadMarkerRoomTimelineView.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -36,7 +27,7 @@ struct ReadMarkerRoomTimelineView: View { } struct ReadMarkerRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock + static let viewModel = TimelineViewModel.mock static let item = ReadMarkerRoomTimelineItem(id: .init(timelineID: .init(UUID().uuidString))) diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/RedactedRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/RedactedRoomTimelineView.swift new file mode 100644 index 0000000000..043c80b88c --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/RedactedRoomTimelineView.swift @@ -0,0 +1,44 @@ +// +// 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 SwiftUI + +struct RedactedRoomTimelineView: View { + let timelineItem: RedactedRoomTimelineItem + + var body: some View { + TimelineStyler(timelineItem: timelineItem) { + Label(timelineItem.body, icon: \.delete, iconSize: .small, relativeTo: .compound.bodyLG) + .labelStyle(RoomTimelineViewLabelStyle()) + .imageScale(.small) // Smaller icon so that the bubble remains rounded on the outside. + } + } +} + +struct RedactedRoomTimelineView_Previews: PreviewProvider, TestablePreview { + static let viewModel = TimelineViewModel.mock + + static var previews: some View { + VStack(alignment: .leading, spacing: 20.0) { + RedactedRoomTimelineView(timelineItem: itemWith(text: L10n.commonMessageRemoved, + timestamp: "Later", + senderId: "Anne")) + } + .environmentObject(viewModel.context) + } + + private static func itemWith(text: String, timestamp: String, senderId: String) -> RedactedRoomTimelineItem { + RedactedRoomTimelineItem(id: .random, + body: text, + timestamp: timestamp, + isOutgoing: false, + isEditable: false, + canBeRepliedTo: false, + sender: .init(id: senderId)) + } +} diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/SeparatorRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/SeparatorRoomTimelineView.swift new file mode 100644 index 0000000000..0f74079076 --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/SeparatorRoomTimelineView.swift @@ -0,0 +1,29 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import SwiftUI + +struct SeparatorRoomTimelineView: View { + let timelineItem: SeparatorRoomTimelineItem + + var body: some View { + Text(timelineItem.text) + .font(.compound.bodySMSemibold) + .foregroundColor(.compound.textPrimary) + .frame(maxWidth: .infinity) + .multilineTextAlignment(.center) + .padding(.horizontal, 36.0) + .padding(.vertical, 8.0) + } +} + +struct SeparatorRoomTimelineView_Previews: PreviewProvider, TestablePreview { + static var previews: some View { + let item = SeparatorRoomTimelineItem(id: .init(timelineID: "Separator"), text: "This is a separator") + SeparatorRoomTimelineView(timelineItem: item) + } +} diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StateRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StateRoomTimelineView.swift new file mode 100644 index 0000000000..47d1a0e055 --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StateRoomTimelineView.swift @@ -0,0 +1,40 @@ +// +// 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 + +struct StateRoomTimelineView: View { + let timelineItem: StateRoomTimelineItem + + var body: some View { + Text(timelineItem.body) + .font(.compound.bodySM) + .multilineTextAlignment(.center) + .foregroundColor(.compound.textSecondary) + .frame(maxWidth: .infinity, alignment: .center) + .padding(.horizontal, 36.0) + .padding(.vertical, 8.0) + } +} + +struct StateRoomTimelineView_Previews: PreviewProvider, TestablePreview { + static var previews: some View { + body + } + + static var body: some View { + StateRoomTimelineView(timelineItem: item) + } + + static let item = StateRoomTimelineItem(id: .random, + body: "Alice joined", + timestamp: "Now", + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + sender: .init(id: "")) +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/StickerRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift similarity index 83% rename from ElementX/Sources/Screens/RoomScreen/View/Timeline/StickerRoomTimelineView.swift rename to ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift index e8805f79da..720d5c49f2 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/StickerRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift @@ -1,31 +1,22 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation import SwiftUI struct StickerRoomTimelineView: View { - @EnvironmentObject private var context: RoomScreenViewModel.Context + @EnvironmentObject private var context: TimelineViewModel.Context let timelineItem: StickerRoomTimelineItem var body: some View { TimelineStyler(timelineItem: timelineItem) { LoadableImage(url: timelineItem.imageURL, blurhash: timelineItem.blurhash, - imageProvider: context.imageProvider) { + mediaProvider: context.mediaProvider) { placeholder } .timelineMediaFrame(height: timelineItem.height, @@ -48,7 +39,7 @@ struct StickerRoomTimelineView: View { } struct StickerRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock + static let viewModel = TimelineViewModel.mock static var previews: some View { body.environmentObject(viewModel.context) diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/TextBasedRoomTimelineViewProtocol.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/TextBasedRoomTimelineViewProtocol.swift new file mode 100644 index 0000000000..d922deee43 --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/TextBasedRoomTimelineViewProtocol.swift @@ -0,0 +1,13 @@ +// +// Copyright 2023, 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +// periphery: ignore - markdown protocol +protocol TextBasedRoomTimelineViewProtocol { + associatedtype TimelineItemType: TextBasedRoomTimelineItem + + var timelineItem: TimelineItemType { get } +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/TextRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/TextRoomTimelineView.swift similarity index 89% rename from ElementX/Sources/Screens/RoomScreen/View/Timeline/TextRoomTimelineView.swift rename to ElementX/Sources/Screens/Timeline/View/TimelineItemViews/TextRoomTimelineView.swift index b2e1cea865..9c0b6cecac 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/TextRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/TextRoomTimelineView.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -36,7 +27,7 @@ struct TextRoomTimelineView: View, TextBasedRoomTimelineViewProtocol { } struct TextRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock + static let viewModel = TimelineViewModel.mock static var previews: some View { body.environmentObject(viewModel.context) diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/TimelineStartRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/TimelineStartRoomTimelineView.swift new file mode 100644 index 0000000000..99625c262b --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/TimelineStartRoomTimelineView.swift @@ -0,0 +1,35 @@ +// +// 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 + +struct TimelineStartRoomTimelineView: View { + let timelineItem: TimelineStartRoomTimelineItem + + var body: some View { + Text(title) + .font(.compound.bodySM) + .foregroundColor(.compound.textSecondary) + .padding(.vertical, 24) + .frame(maxWidth: .infinity) + } + + var title: String { + var text = L10n.screenRoomTimelineBeginningOfRoomNoName + if let name = timelineItem.name { + text = L10n.screenRoomTimelineBeginningOfRoom(name) + } + return text + } +} + +struct TimelineStartRoomTimelineView_Previews: PreviewProvider, TestablePreview { + static var previews: some View { + let item = TimelineStartRoomTimelineItem(name: "Alice and Bob") + TimelineStartRoomTimelineView(timelineItem: item) + } +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/UnsupportedRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/UnsupportedRoomTimelineView.swift similarity index 79% rename from ElementX/Sources/Screens/RoomScreen/View/Timeline/UnsupportedRoomTimelineView.swift rename to ElementX/Sources/Screens/Timeline/View/TimelineItemViews/UnsupportedRoomTimelineView.swift index d76d5509c3..0f5da6dee3 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/UnsupportedRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/UnsupportedRoomTimelineView.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -40,7 +31,7 @@ struct UnsupportedRoomTimelineView: View { } struct UnsupportedRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock + static let viewModel = TimelineViewModel.mock static var previews: some View { body.environmentObject(viewModel.context) diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/VideoRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift similarity index 84% rename from ElementX/Sources/Screens/RoomScreen/View/Timeline/VideoRoomTimelineView.swift rename to ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift index 7df573380e..c681f0e3be 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/VideoRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift @@ -1,24 +1,15 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation import SwiftUI struct VideoRoomTimelineView: View { - @EnvironmentObject private var context: RoomScreenViewModel.Context + @EnvironmentObject private var context: TimelineViewModel.Context let timelineItem: VideoRoomTimelineItem var body: some View { @@ -36,7 +27,7 @@ struct VideoRoomTimelineView: View { if let thumbnailSource = timelineItem.content.thumbnailSource { LoadableImage(mediaSource: thumbnailSource, blurhash: timelineItem.content.blurhash, - imageProvider: context.imageProvider) { imageView in + mediaProvider: context.mediaProvider) { imageView in imageView .overlay { playIcon } } placeholder: { @@ -68,7 +59,7 @@ struct VideoRoomTimelineView: View { } struct VideoRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock + static let viewModel = TimelineViewModel.mock static var previews: some View { body.environmentObject(viewModel.context) diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineSenderAvatarView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineSenderAvatarView.swift new file mode 100644 index 0000000000..4dd222bcec --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/TimelineSenderAvatarView.swift @@ -0,0 +1,26 @@ +// +// 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 SwiftUI + +struct TimelineSenderAvatarView: View { + @EnvironmentObject private var context: TimelineViewModel.Context + + let timelineItem: EventBasedTimelineItemProtocol + + var body: some View { + LoadableAvatarImage(url: timelineItem.sender.avatarURL, + name: timelineItem.sender.displayName, + contentID: timelineItem.sender.id, + avatarSize: .user(on: .timeline), + mediaProvider: context.mediaProvider) + .overlay { + Circle().stroke(Color.compound.bgCanvasDefault, lineWidth: 3) + } + } +} diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineView.swift new file mode 100644 index 0000000000..c7dbde17d1 --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/TimelineView.swift @@ -0,0 +1,98 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import SwiftUI +import WysiwygComposer + +/// A table view wrapper that displays the timeline of a room. +struct TimelineView: UIViewControllerRepresentable { + @EnvironmentObject private var viewModelContext: TimelineViewModel.Context + @Environment(\.openURL) var openURL + + func makeUIViewController(context: Context) -> TimelineTableViewController { + let tableViewController = TimelineTableViewController(coordinator: context.coordinator, + isScrolledToBottom: $viewModelContext.isScrolledToBottom, + scrollToBottomPublisher: viewModelContext.viewState.timelineViewState.scrollToBottomPublisher) + // Needs to be dispatched on main asynchronously otherwise we get a runtime warning + DispatchQueue.main.async { + viewModelContext.send(viewAction: .setOpenURLAction(openURL)) + } + return tableViewController + } + + func updateUIViewController(_ uiViewController: TimelineTableViewController, context: Context) { + context.coordinator.update(tableViewController: uiViewController) + } + + func makeCoordinator() -> Coordinator { + Coordinator(viewModelContext: viewModelContext) + } + + // MARK: - Coordinator + + @MainActor + class Coordinator { + let context: TimelineViewModel.Context + + init(viewModelContext: TimelineViewModel.Context) { + context = viewModelContext + } + + /// Updates the specified table view's properties from the current view state. + func update(tableViewController: TimelineTableViewController) { + if tableViewController.isSwitchingTimelines != context.viewState.timelineViewState.isSwitchingTimelines { + // Must come before timelineItemsDictionary in order to disable animations. + tableViewController.isSwitchingTimelines = context.viewState.timelineViewState.isSwitchingTimelines + } + if tableViewController.timelineItemsDictionary != context.viewState.timelineViewState.itemsDictionary { + tableViewController.timelineItemsDictionary = context.viewState.timelineViewState.itemsDictionary + } + if tableViewController.paginationState != context.viewState.timelineViewState.paginationState { + tableViewController.paginationState = context.viewState.timelineViewState.paginationState + } + if tableViewController.isLive != context.viewState.timelineViewState.isLive { + tableViewController.isLive = context.viewState.timelineViewState.isLive + } + if tableViewController.focussedEvent != context.viewState.timelineViewState.focussedEvent { + tableViewController.focussedEvent = context.viewState.timelineViewState.focussedEvent + } + + if tableViewController.typingMembers.members != context.viewState.typingMembers { + tableViewController.setTypingMembers(context.viewState.typingMembers) + } + } + + func send(viewAction: TimelineViewAction) { + context.send(viewAction: viewAction) + } + } +} + +// MARK: - Previews + +struct TimelineView_Previews: PreviewProvider, TestablePreview { + static let roomProxyMock = JoinedRoomProxyMock(.init(id: "stable_id", + name: "Preview room")) + static let roomViewModel = RoomScreenViewModel.mock(roomProxyMock: roomProxyMock) + static let timelineViewModel = TimelineViewModel(roomProxy: roomProxyMock, + timelineController: MockRoomTimelineController(), + mediaProvider: MockMediaProvider(), + mediaPlayerProvider: MediaPlayerProviderMock(), + voiceMessageMediaManager: VoiceMessageMediaManagerMock(), + userIndicatorController: ServiceLocator.shared.userIndicatorController, + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) + + static var previews: some View { + NavigationStack { + RoomScreen(roomViewModel: roomViewModel, + timelineViewModel: timelineViewModel, + composerToolbar: ComposerToolbar.mock()) + } + } +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/TypingIndicatorView.swift b/ElementX/Sources/Screens/Timeline/View/TypingIndicatorView.swift similarity index 84% rename from ElementX/Sources/Screens/RoomScreen/View/Timeline/TypingIndicatorView.swift rename to ElementX/Sources/Screens/Timeline/View/TypingIndicatorView.swift index b1853a21cb..da3d805e2c 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/TypingIndicatorView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TypingIndicatorView.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenCoordinator.swift b/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenCoordinator.swift index b32a04f2df..1c9d98d9ca 100644 --- a/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenCoordinator.swift +++ b/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenModels.swift b/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenModels.swift index 10ed9bf622..83a95a65fa 100644 --- a/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenModels.swift +++ b/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModel.swift b/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModel.swift index 63d87be190..8abf9be3e2 100644 --- a/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModel.swift +++ b/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -47,7 +38,7 @@ class UserProfileScreenViewModel: UserProfileScreenViewModelType, UserProfileScr isPresentedModally: isPresentedModally, bindings: .init()) - super.init(initialViewState: initialViewState, imageProvider: mediaProvider) + super.init(initialViewState: initialViewState, mediaProvider: mediaProvider) showLoadingIndicator(allowsInteraction: true) Task { diff --git a/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModelProtocol.swift b/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModelProtocol.swift index c885878991..cb783dfe8f 100644 --- a/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModelProtocol.swift +++ b/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift b/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift index a325c289e8..43201a3bb4 100644 --- a/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift +++ b/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -30,7 +21,7 @@ struct UserProfileScreen: View { .toolbar { toolbar } .alert(item: $context.alertInfo) .track(screen: .User) - .interactiveQuickLook(item: $context.mediaPreviewItem, shouldHideControls: true) + .interactiveQuickLook(item: $context.mediaPreviewItem, allowEditing: false) } // MARK: - Private @@ -72,7 +63,7 @@ struct UserProfileScreen: View { if let userProfile = context.viewState.userProfile { AvatarHeaderView(user: userProfile, avatarSize: .user(on: .memberDetails), - imageProvider: context.imageProvider) { + mediaProvider: context.mediaProvider) { context.send(viewAction: .displayAvatar) } footer: { otherUserFooter @@ -80,7 +71,7 @@ struct UserProfileScreen: View { } else { AvatarHeaderView(user: UserProfileProxy(userID: context.viewState.userID), avatarSize: .user(on: .memberDetails), - imageProvider: context.imageProvider, + mediaProvider: context.mediaProvider, footer: { }) } } @@ -106,10 +97,10 @@ struct UserProfileScreen_Previews: PreviewProvider, TestablePreview { static var previews: some View { UserProfileScreen(context: otherUserViewModel.context) .previewDisplayName("Other User") - .snapshot(delay: 0.25) + .snapshotPreferences(delay: 0.25) UserProfileScreen(context: accountOwnerViewModel.context) .previewDisplayName("Account Owner") - .snapshot(delay: 0.25) + .snapshotPreferences(delay: 0.25) } static func makeViewModel(userID: String) -> UserProfileScreenViewModel { diff --git a/ElementX/Sources/Services/Analytics/AnalyticsClientProtocol.swift b/ElementX/Sources/Services/Analytics/AnalyticsClientProtocol.swift index 465941667d..4092ac39da 100644 --- a/ElementX/Sources/Services/Analytics/AnalyticsClientProtocol.swift +++ b/ElementX/Sources/Services/Analytics/AnalyticsClientProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2021 New Vector Ltd +// Copyright 2021-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import AnalyticsEvents diff --git a/ElementX/Sources/Services/Analytics/AnalyticsConfiguration.swift b/ElementX/Sources/Services/Analytics/AnalyticsConfiguration.swift index 96a321ff17..4d829e83d7 100644 --- a/ElementX/Sources/Services/Analytics/AnalyticsConfiguration.swift +++ b/ElementX/Sources/Services/Analytics/AnalyticsConfiguration.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Analytics/AnalyticsConsentState.swift b/ElementX/Sources/Services/Analytics/AnalyticsConsentState.swift index f8805803e0..b7072fab4b 100644 --- a/ElementX/Sources/Services/Analytics/AnalyticsConsentState.swift +++ b/ElementX/Sources/Services/Analytics/AnalyticsConsentState.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Analytics/AnalyticsService.swift b/ElementX/Sources/Services/Analytics/AnalyticsService.swift index c3076d0b86..3ecbed8054 100644 --- a/ElementX/Sources/Services/Analytics/AnalyticsService.swift +++ b/ElementX/Sources/Services/Analytics/AnalyticsService.swift @@ -1,17 +1,8 @@ // -// Copyright 2021 New Vector Ltd +// Copyright 2021-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import AnalyticsEvents @@ -252,4 +243,8 @@ extension AnalyticsService { func updateUserProperties(_ userProperties: AnalyticsEvent.UserProperties) { client.updateUserProperties(userProperties) } + + func trackPinUnpinEvent(_ event: AnalyticsEvent.PinUnpinAction) { + capture(event: event) + } } diff --git a/ElementX/Sources/Services/Analytics/Helpers/Analytics+SwiftUI.swift b/ElementX/Sources/Services/Analytics/Helpers/Analytics+SwiftUI.swift index 4e74ca59dd..cdc573bc69 100644 --- a/ElementX/Sources/Services/Analytics/Helpers/Analytics+SwiftUI.swift +++ b/ElementX/Sources/Services/Analytics/Helpers/Analytics+SwiftUI.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/Sources/Services/Analytics/Helpers/JoinedRoomSize+MemberCount.swift b/ElementX/Sources/Services/Analytics/Helpers/JoinedRoomSize+MemberCount.swift index 074f1e2d1d..60b0e18a0f 100644 --- a/ElementX/Sources/Services/Analytics/Helpers/JoinedRoomSize+MemberCount.swift +++ b/ElementX/Sources/Services/Analytics/Helpers/JoinedRoomSize+MemberCount.swift @@ -1,17 +1,8 @@ // -// Copyright 2021 New Vector Ltd +// Copyright 2021-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import AnalyticsEvents diff --git a/ElementX/Sources/Services/Analytics/Helpers/RoomModerationRole.swift b/ElementX/Sources/Services/Analytics/Helpers/RoomModerationRole.swift index a0a8586810..a51c3a9868 100644 --- a/ElementX/Sources/Services/Analytics/Helpers/RoomModerationRole.swift +++ b/ElementX/Sources/Services/Analytics/Helpers/RoomModerationRole.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import AnalyticsEvents diff --git a/ElementX/Sources/Services/Analytics/PHGPostHogConfiguration.swift b/ElementX/Sources/Services/Analytics/PHGPostHogConfiguration.swift index 64db62400e..875e1c36e8 100644 --- a/ElementX/Sources/Services/Analytics/PHGPostHogConfiguration.swift +++ b/ElementX/Sources/Services/Analytics/PHGPostHogConfiguration.swift @@ -1,17 +1,8 @@ // -// Copyright 2021 New Vector Ltd +// Copyright 2021-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import PostHog diff --git a/ElementX/Sources/Services/Analytics/PHGPostHogProtocol.swift b/ElementX/Sources/Services/Analytics/PHGPostHogProtocol.swift index dbb0d120e6..92c654a85b 100644 --- a/ElementX/Sources/Services/Analytics/PHGPostHogProtocol.swift +++ b/ElementX/Sources/Services/Analytics/PHGPostHogProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Analytics/PostHogAnalyticsClient.swift b/ElementX/Sources/Services/Analytics/PostHogAnalyticsClient.swift index 83ed3469c6..17437d5cca 100644 --- a/ElementX/Sources/Services/Analytics/PostHogAnalyticsClient.swift +++ b/ElementX/Sources/Services/Analytics/PostHogAnalyticsClient.swift @@ -1,17 +1,8 @@ // -// Copyright 2021 New Vector Ltd +// Copyright 2021-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import AnalyticsEvents diff --git a/ElementX/Sources/Services/Analytics/Signposter.swift b/ElementX/Sources/Services/Analytics/Signposter.swift index f879854729..2f7eca4d05 100644 --- a/ElementX/Sources/Services/Analytics/Signposter.swift +++ b/ElementX/Sources/Services/Analytics/Signposter.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import OSLog diff --git a/ElementX/Sources/Services/Analytics/UserPropertiesExt.swift b/ElementX/Sources/Services/Analytics/UserPropertiesExt.swift index 6228e94507..285b97c9d0 100644 --- a/ElementX/Sources/Services/Analytics/UserPropertiesExt.swift +++ b/ElementX/Sources/Services/Analytics/UserPropertiesExt.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import AnalyticsEvents diff --git a/ElementX/Sources/Services/AppLock/AppLockService.swift b/ElementX/Sources/Services/AppLock/AppLockService.swift index c222765385..c9765303c0 100644 --- a/ElementX/Sources/Services/AppLock/AppLockService.swift +++ b/ElementX/Sources/Services/AppLock/AppLockService.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Services/AppLock/AppLockServiceProtocol.swift b/ElementX/Sources/Services/AppLock/AppLockServiceProtocol.swift index 1d48e2d948..f7f4429e64 100644 --- a/ElementX/Sources/Services/AppLock/AppLockServiceProtocol.swift +++ b/ElementX/Sources/Services/AppLock/AppLockServiceProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Services/AppLock/AppLockTimer.swift b/ElementX/Sources/Services/AppLock/AppLockTimer.swift index 5aa8f908db..d512ba0e44 100644 --- a/ElementX/Sources/Services/AppLock/AppLockTimer.swift +++ b/ElementX/Sources/Services/AppLock/AppLockTimer.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/AppLock/LAContextMock.swift b/ElementX/Sources/Services/AppLock/LAContextMock.swift index 0640693c45..68cc6a8660 100644 --- a/ElementX/Sources/Services/AppLock/LAContextMock.swift +++ b/ElementX/Sources/Services/AppLock/LAContextMock.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import LocalAuthentication diff --git a/ElementX/Sources/Services/Audio/AudioConverter.swift b/ElementX/Sources/Services/Audio/AudioConverter.swift index 8b3273864c..4adc7c0241 100644 --- a/ElementX/Sources/Services/Audio/AudioConverter.swift +++ b/ElementX/Sources/Services/Audio/AudioConverter.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import AVFoundation diff --git a/ElementX/Sources/Services/Audio/AudioConverterProtocol.swift b/ElementX/Sources/Services/Audio/AudioConverterProtocol.swift index c108a82ad0..331d448af3 100644 --- a/ElementX/Sources/Services/Audio/AudioConverterProtocol.swift +++ b/ElementX/Sources/Services/Audio/AudioConverterProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Audio/AudioSessionProtocol.swift b/ElementX/Sources/Services/Audio/AudioSessionProtocol.swift index 7a0e913aa6..97dffdcac7 100644 --- a/ElementX/Sources/Services/Audio/AudioSessionProtocol.swift +++ b/ElementX/Sources/Services/Audio/AudioSessionProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import AVFoundation diff --git a/ElementX/Sources/Services/Audio/Player/AudioPlayer.swift b/ElementX/Sources/Services/Audio/Player/AudioPlayer.swift index 74bbab65d6..79a1a3a5a9 100644 --- a/ElementX/Sources/Services/Audio/Player/AudioPlayer.swift +++ b/ElementX/Sources/Services/Audio/Player/AudioPlayer.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import AVFoundation @@ -142,7 +133,7 @@ class AudioPlayer: NSObject, AudioPlayerProtocol { private func setupAudioSession() { releaseAudioSessionTask = nil do { - try audioSession.setCategory(AVAudioSession.Category.playback) + try audioSession.setCategory(.playback) try audioSession.setActive(true) } catch { MXLog.error("Could not redirect audio playback to speakers.") @@ -157,8 +148,8 @@ class AudioPlayer: NSObject, AudioPlayerProtocol { releaseAudioSessionTask = Task { [weak self] in try? await Task.sleep(for: .seconds(timeInterval)) guard !Task.isCancelled else { return } - guard let self else { return } - self.releaseAudioSession() + + self?.releaseAudioSession() } } @@ -166,7 +157,7 @@ class AudioPlayer: NSObject, AudioPlayerProtocol { releaseAudioSessionTask = nil if audioSession.category == .playback, !audioSession.isOtherAudioPlaying { MXLog.info("releasing audio session") - try? audioSession.setActive(false) + try? audioSession.setActive(false, options: .notifyOthersOnDeactivation) } } @@ -189,10 +180,10 @@ class AudioPlayer: NSObject, AudioPlayerProtocol { switch playerItem.status { case .failed: - self.setInternalState(.error(playerItem.error ?? AudioPlayerError.genericError)) + setInternalState(.error(playerItem.error ?? AudioPlayerError.genericError)) case .readyToPlay: guard state == .loading else { return } - self.setInternalState(.readyToPlay) + setInternalState(.readyToPlay) default: break } @@ -202,30 +193,20 @@ class AudioPlayer: NSObject, AudioPlayerProtocol { guard let self else { return } if internalAudioPlayer.rate == 0 { - if self.isStopped { - self.setInternalState(.stopped) + if isStopped { + setInternalState(.stopped) } else { - self.setInternalState(.paused) + setInternalState(.paused) } } else { - self.setInternalState(.playing) + setInternalState(.playing) } } NotificationCenter.default.publisher(for: Notification.Name.AVPlayerItemDidPlayToEndTime) .sink { [weak self] _ in guard let self else { return } - self.setInternalState(.finishedPlaying) - } - .store(in: &cancellables) - - // Pause playback uppon UIApplication.didBecomeActiveNotification notification - NotificationCenter.default.publisher(for: UIApplication.didEnterBackgroundNotification) - .sink { [weak self] _ in - guard let self else { return } - self.pause() - // Release the audio session right away, as we don't play audio in the background - self.releaseAudioSession() + setInternalState(.finishedPlaying) } .store(in: &cancellables) } diff --git a/ElementX/Sources/Services/Audio/Player/AudioPlayerProtocol.swift b/ElementX/Sources/Services/Audio/Player/AudioPlayerProtocol.swift index 8be7a4a886..7addac3f3a 100644 --- a/ElementX/Sources/Services/Audio/Player/AudioPlayerProtocol.swift +++ b/ElementX/Sources/Services/Audio/Player/AudioPlayerProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Services/Audio/Player/AudioPlayerState.swift b/ElementX/Sources/Services/Audio/Player/AudioPlayerState.swift index 69b75e3129..b0ab2abc31 100644 --- a/ElementX/Sources/Services/Audio/Player/AudioPlayerState.swift +++ b/ElementX/Sources/Services/Audio/Player/AudioPlayerState.swift @@ -1,21 +1,13 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine import Foundation +import MediaPlayer import UIKit enum AudioPlayerPlaybackState { @@ -34,16 +26,15 @@ enum AudioPlayerStateIdentifier { @MainActor class AudioPlayerState: ObservableObject, Identifiable { let id: AudioPlayerStateIdentifier + let title: String private(set) var duration: Double let waveform: EstimatedWaveform + @Published private(set) var progress: Double + @Published private(set) var playbackState: AudioPlayerPlaybackState /// It's similar to `playbackState`, with the a difference: `.loading` /// updates are delayed by a fixed amount of time @Published private(set) var playerButtonPlaybackState: AudioPlayerPlaybackState - @Published private(set) var progress: Double - var showProgressIndicator: Bool { - progress > 0 - } private weak var audioPlayer: AudioPlayerProtocol? private var audioPlayerSubscription: AnyCancellable? @@ -53,6 +44,10 @@ class AudioPlayerState: ObservableObject, Identifiable { /// The file url that the last player attached to this object has loaded. /// The file url persists even if the AudioPlayer will be detached later. private(set) var fileURL: URL? + + var showProgressIndicator: Bool { + progress > 0 + } var isAttached: Bool { audioPlayer != nil @@ -62,8 +57,9 @@ class AudioPlayerState: ObservableObject, Identifiable { displayLink != nil } - init(id: AudioPlayerStateIdentifier, duration: Double, waveform: EstimatedWaveform? = nil, progress: Double = 0.0) { + init(id: AudioPlayerStateIdentifier, title: String, duration: Double, waveform: EstimatedWaveform? = nil, progress: Double = 0.0) { self.id = id + self.title = title self.duration = duration self.waveform = waveform ?? EstimatedWaveform(data: []) self.progress = progress @@ -146,12 +142,19 @@ class AudioPlayerState: ObservableObject, Identifiable { } startPublishProgress() playbackState = .playing - case .didPausePlaying, .didStopPlaying, .didFinishPlaying: + setUpRemoteCommandCenter() + case .didPausePlaying: stopPublishProgress() playbackState = .stopped - if case .didFinishPlaying = action { - progress = 0.0 - } + case .didStopPlaying: + playbackState = .stopped + stopPublishProgress() + tearDownRemoteCommandCenter() + case .didFinishPlaying: + playbackState = .stopped + progress = 0.0 + stopPublishProgress() + tearDownRemoteCommandCenter() case .didFailWithError: stopPublishProgress() playbackState = .error @@ -172,6 +175,8 @@ class AudioPlayerState: ObservableObject, Identifiable { if let currentTime = audioPlayer?.currentTime, duration > 0 { progress = currentTime / duration } + + updateNowPlayingInfoCenter() } private func stopPublishProgress() { @@ -200,6 +205,93 @@ class AudioPlayerState: ObservableObject, Identifiable { .removeDuplicates() .weakAssign(to: \.playerButtonPlaybackState, on: self) } + + private func setUpRemoteCommandCenter() { + UIApplication.shared.beginReceivingRemoteControlEvents() + + let commandCenter = MPRemoteCommandCenter.shared() + + commandCenter.playCommand.isEnabled = true + commandCenter.playCommand.removeTarget(nil) + commandCenter.playCommand.addTarget { [weak self] _ in + guard let audioPlayer = self?.audioPlayer else { + return MPRemoteCommandHandlerStatus.commandFailed + } + + audioPlayer.play() + + return MPRemoteCommandHandlerStatus.success + } + + commandCenter.pauseCommand.isEnabled = true + commandCenter.pauseCommand.removeTarget(nil) + commandCenter.pauseCommand.addTarget { [weak self] _ in + guard let audioPlayer = self?.audioPlayer else { + return MPRemoteCommandHandlerStatus.commandFailed + } + + audioPlayer.pause() + + return MPRemoteCommandHandlerStatus.success + } + + commandCenter.skipForwardCommand.isEnabled = true + commandCenter.skipForwardCommand.removeTarget(nil) + commandCenter.skipForwardCommand.addTarget { [weak self] event in + guard let audioPlayer = self?.audioPlayer, let skipEvent = event as? MPSkipIntervalCommandEvent else { + return MPRemoteCommandHandlerStatus.commandFailed + } + + Task { + await audioPlayer.seek(to: audioPlayer.currentTime + skipEvent.interval) + } + + return MPRemoteCommandHandlerStatus.success + } + + commandCenter.skipBackwardCommand.isEnabled = true + commandCenter.skipBackwardCommand.removeTarget(nil) + commandCenter.skipBackwardCommand.addTarget { [weak self] event in + guard let audioPlayer = self?.audioPlayer, let skipEvent = event as? MPSkipIntervalCommandEvent else { + return MPRemoteCommandHandlerStatus.commandFailed + } + + Task { + await audioPlayer.seek(to: audioPlayer.currentTime - skipEvent.interval) + } + + return MPRemoteCommandHandlerStatus.success + } + } + + private func tearDownRemoteCommandCenter() { + UIApplication.shared.endReceivingRemoteControlEvents() + + let nowPlayingInfoCenter = MPNowPlayingInfoCenter.default() + nowPlayingInfoCenter.nowPlayingInfo = nil + nowPlayingInfoCenter.playbackState = .stopped + + let commandCenter = MPRemoteCommandCenter.shared() + commandCenter.playCommand.isEnabled = false + commandCenter.playCommand.removeTarget(nil) + commandCenter.pauseCommand.isEnabled = false + commandCenter.pauseCommand.removeTarget(nil) + commandCenter.skipForwardCommand.isEnabled = false + commandCenter.skipForwardCommand.removeTarget(nil) + commandCenter.skipBackwardCommand.isEnabled = false + commandCenter.skipBackwardCommand.removeTarget(nil) + } + + private func updateNowPlayingInfoCenter() { + guard let audioPlayer else { + return + } + + let nowPlayingInfoCenter = MPNowPlayingInfoCenter.default() + nowPlayingInfoCenter.nowPlayingInfo = [MPMediaItemPropertyTitle: title, + MPMediaItemPropertyPlaybackDuration: audioPlayer.duration as Any, + MPNowPlayingInfoPropertyElapsedPlaybackTime: audioPlayer.currentTime as Any] + } } extension AudioPlayerState: Equatable { diff --git a/ElementX/Sources/Services/Audio/Recorder/AudioRecorder.swift b/ElementX/Sources/Services/Audio/Recorder/AudioRecorder.swift index 80f39db142..2353769a3f 100644 --- a/ElementX/Sources/Services/Audio/Recorder/AudioRecorder.swift +++ b/ElementX/Sources/Services/Audio/Recorder/AudioRecorder.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Accelerate @@ -128,7 +119,7 @@ class AudioRecorder: AudioRecorderProtocol { private func releaseAudioSession() { MXLog.info("releasing audio session") - try? audioSession.setActive(false) + try? audioSession.setActive(false, options: .notifyOthersOnDeactivation) removeObservers() } @@ -372,6 +363,7 @@ class AudioRecorder: AudioRecorderProtocol { case .began: MXLog.info("Interruption started: \(notification)") setInternalState(.suspended) + case .ended: MXLog.info("Interruption ended: \(notification)") diff --git a/ElementX/Sources/Services/Audio/Recorder/AudioRecorderProtocol.swift b/ElementX/Sources/Services/Audio/Recorder/AudioRecorderProtocol.swift index fc59227731..780b5b73b4 100644 --- a/ElementX/Sources/Services/Audio/Recorder/AudioRecorderProtocol.swift +++ b/ElementX/Sources/Services/Audio/Recorder/AudioRecorderProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Services/Audio/Recorder/AudioRecorderState.swift b/ElementX/Sources/Services/Audio/Recorder/AudioRecorderState.swift index d53d7d5a56..d33e95d45e 100644 --- a/ElementX/Sources/Services/Audio/Recorder/AudioRecorderState.swift +++ b/ElementX/Sources/Services/Audio/Recorder/AudioRecorderState.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Services/Authentication/AuthenticationClientBuilder.swift b/ElementX/Sources/Services/Authentication/AuthenticationClientBuilder.swift new file mode 100644 index 0000000000..350e388246 --- /dev/null +++ b/ElementX/Sources/Services/Authentication/AuthenticationClientBuilder.swift @@ -0,0 +1,78 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Foundation +import MatrixRustSDK + +/// A wrapper around `ClientBuilder` to share reusable code between Normal and QR logins. +struct AuthenticationClientBuilder { + let sessionDirectories: SessionDirectories + let passphrase: String + let clientSessionDelegate: ClientSessionDelegate + + let appSettings: AppSettings + let appHooks: AppHooks + + /// Builds a Client for login using OIDC or password authentication. + func build(homeserverAddress: String) async throws -> Client { + if appSettings.slidingSyncDiscovery == .forceNative { + return try await makeClientBuilder(slidingSync: .forceNative).serverNameOrHomeserverUrl(serverNameOrUrl: homeserverAddress).build() + } + + if appSettings.slidingSyncDiscovery == .native { + do { + return try await makeClientBuilder(slidingSync: .discoverNative).serverNameOrHomeserverUrl(serverNameOrUrl: homeserverAddress).build() + } catch { + MXLog.warning("Native sliding sync not available: \(error)") + MXLog.info("Falling back to a sliding sync proxy.") + } + } + + return try await makeClientBuilder(slidingSync: .discoverProxy).serverNameOrHomeserverUrl(serverNameOrUrl: homeserverAddress).build() + } + + /// Builds a Client, authenticating with the given QR code data. + func buildWithQRCode(qrCodeData: QrCodeData, + oidcConfiguration: OIDCConfigurationProxy, + progressListener: QrLoginProgressListenerProxy) async throws -> Client { + if appSettings.slidingSyncDiscovery == .forceNative { + return try await makeClientBuilder(slidingSync: .forceNative).buildWithQrCode(qrCodeData: qrCodeData, + oidcConfiguration: oidcConfiguration.rustValue, + progressListener: progressListener) + } + + if appSettings.slidingSyncDiscovery == .native { + do { + return try await makeClientBuilder(slidingSync: .discoverNative).buildWithQrCode(qrCodeData: qrCodeData, + oidcConfiguration: oidcConfiguration.rustValue, + progressListener: progressListener) + } catch HumanQrLoginError.SlidingSyncNotAvailable { + MXLog.warning("Native sliding sync not available") + MXLog.info("Falling back to a sliding sync proxy.") + } + } + + return try await makeClientBuilder(slidingSync: .discoverProxy).buildWithQrCode(qrCodeData: qrCodeData, + oidcConfiguration: oidcConfiguration.rustValue, + progressListener: progressListener) + } + + // MARK: - Private + + /// The base builder configuration used for authentication within the app. + private func makeClientBuilder(slidingSync: ClientBuilderSlidingSync) -> ClientBuilder { + ClientBuilder + .baseBuilder(httpProxy: appSettings.websiteURL.globalProxy, + slidingSync: slidingSync, + sessionDelegate: clientSessionDelegate, + appHooks: appHooks, + invisibleCryptoEnabled: appSettings.invisibleCryptoEnabled) + .sessionPaths(dataPath: sessionDirectories.dataPath, + cachePath: sessionDirectories.cachePath) + .passphrase(passphrase: passphrase) + } +} diff --git a/ElementX/Sources/Services/Authentication/AuthenticationService.swift b/ElementX/Sources/Services/Authentication/AuthenticationService.swift index fada236e69..c799a8f313 100644 --- a/ElementX/Sources/Services/Authentication/AuthenticationService.swift +++ b/ElementX/Sources/Services/Authentication/AuthenticationService.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -20,7 +11,7 @@ import MatrixRustSDK class AuthenticationService: AuthenticationServiceProtocol { private var client: Client? - private var sessionDirectory: URL + private var sessionDirectories: SessionDirectories private let passphrase: String private let userSessionStore: UserSessionStoreProtocol @@ -31,7 +22,7 @@ class AuthenticationService: AuthenticationServiceProtocol { var homeserver: CurrentValuePublisher { homeserverSubject.asCurrentValuePublisher() } init(userSessionStore: UserSessionStoreProtocol, encryptionKeyProvider: EncryptionKeyProviderProtocol, appSettings: AppSettings, appHooks: AppHooks) { - sessionDirectory = .sessionsBaseDirectory.appending(component: UUID().uuidString) + sessionDirectories = .init() passphrase = encryptionKeyProvider.generateKey().base64EncodedString() self.userSessionStore = userSessionStore self.appSettings = appSettings @@ -47,15 +38,23 @@ class AuthenticationService: AuthenticationServiceProtocol { do { var homeserver = LoginHomeserver(address: homeserverAddress, loginMode: .unknown) - let client = try await makeClientBuilder().serverNameOrHomeserverUrl(serverNameOrUrl: homeserverAddress).build() + let client = try await makeClientBuilder().build(homeserverAddress: homeserverAddress) let loginDetails = await client.homeserverLoginDetails() + let elementWellKnown = await client.getElementWellKnown() + + MXLog.info("Sliding sync: \(client.slidingSyncVersion())") - if loginDetails.supportsOidcLogin() { - homeserver.loginMode = .oidc + homeserver.loginMode = if loginDetails.supportsOidcLogin() { + .oidc } else if loginDetails.supportsPasswordLogin() { - homeserver.loginMode = .password + .password } else { - homeserver.loginMode = .unsupported + .unsupported + } + + homeserver.registrationHelperURL = switch elementWellKnown { + case .success(let wellKnown): wellKnown.registrationHelperUrl.flatMap(URL.init) + case .failure: nil } self.client = client @@ -64,8 +63,8 @@ class AuthenticationService: AuthenticationServiceProtocol { } catch ClientBuildError.WellKnownDeserializationError(let error) { MXLog.error("The user entered a server with an invalid well-known file: \(error)") return .failure(.invalidWellKnown(error)) - } catch ClientBuildError.SlidingSyncNotAvailable { - MXLog.info("User entered a homeserver that isn't configured for sliding sync.") + } catch ClientBuildError.SlidingSyncVersion(let error) { + MXLog.info("User entered a homeserver that isn't configured for sliding sync: \(error)") return .failure(.slidingSyncNotAvailable) } catch { MXLog.error("Failed configuring a server: \(error)") @@ -121,10 +120,6 @@ class AuthenticationService: AuthenticationServiceProtocol { // FIXME: How about we make a proper type in the FFI? ๐Ÿ˜… guard let error = error as? ClientError else { return .failure(.failedLoggingIn) } - if error.isElementWaitlist { - return .failure(.isOnWaitlist) - } - switch error.code { case .forbidden: return .failure(.invalidCredentials) @@ -136,33 +131,46 @@ class AuthenticationService: AuthenticationServiceProtocol { } } + func completeWebRegistration(using credentials: WebRegistrationCredentials) async -> Result { + guard let client else { return .failure(.failedLoggingIn) } + let session = Session(accessToken: credentials.accessToken, + refreshToken: nil, + userId: credentials.userID, + deviceId: credentials.deviceID, + homeserverUrl: client.homeserver(), + oidcData: nil, + slidingSyncVersion: client.slidingSyncVersion()) + + do { + try await client.restoreSession(session: session) + return await userSession(for: client) + } catch { + MXLog.error("Failed restoring the client using the provided credentials.") + return .failure(.failedUsingWebCredentials) + } + } + // MARK: - Private - private func makeClientBuilder() -> ClientBuilder { + private func makeClientBuilder() -> AuthenticationClientBuilder { // Use a fresh session directory each time the user enters a different server // so that caches (e.g. server versions) are always fresh for the new server. rotateSessionDirectory() - return ClientBuilder - .baseBuilder(httpProxy: appSettings.websiteURL.globalProxy, - slidingSync: appSettings.simplifiedSlidingSyncEnabled ? .simplified : .discovered, - slidingSyncProxy: appSettings.slidingSyncProxyURL, - sessionDelegate: userSessionStore.clientSessionDelegate, - appHooks: appHooks) - .sessionPath(path: sessionDirectory.path(percentEncoded: false)) - .passphrase(passphrase: passphrase) + return AuthenticationClientBuilder(sessionDirectories: sessionDirectories, + passphrase: passphrase, + clientSessionDelegate: userSessionStore.clientSessionDelegate, + appSettings: appSettings, + appHooks: appHooks) } private func rotateSessionDirectory() { - if FileManager.default.directoryExists(at: sessionDirectory) { - try? FileManager.default.removeItem(at: sessionDirectory) - } - - sessionDirectory = .sessionsBaseDirectory.appending(component: UUID().uuidString) + sessionDirectories.delete() + sessionDirectories = .init() } private func userSession(for client: Client) async -> Result { - switch await userSessionStore.userSession(for: client, sessionDirectory: sessionDirectory, passphrase: passphrase) { + switch await userSessionStore.userSession(for: client, sessionDirectories: sessionDirectories, passphrase: passphrase) { case .success(let clientProxy): return .success(clientProxy) case .failure: diff --git a/ElementX/Sources/Services/Authentication/AuthenticationServiceProtocol.swift b/ElementX/Sources/Services/Authentication/AuthenticationServiceProtocol.swift index 4051da7c4c..e347bc7b98 100644 --- a/ElementX/Sources/Services/Authentication/AuthenticationServiceProtocol.swift +++ b/ElementX/Sources/Services/Authentication/AuthenticationServiceProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -35,8 +26,8 @@ enum AuthenticationServiceError: Error { case slidingSyncNotAvailable case accountDeactivated case failedLoggingIn - case isOnWaitlist case sessionTokenRefreshNotSupported + case failedUsingWebCredentials } protocol AuthenticationServiceProtocol { @@ -53,6 +44,8 @@ protocol AuthenticationServiceProtocol { func loginWithOIDCCallback(_ callbackURL: URL, data: OIDCAuthorizationDataProxy) async -> Result /// Performs a password login using the current homeserver. func login(username: String, password: String, initialDeviceName: String?, deviceID: String?) async -> Result + /// Completes registration using the credentials obtained via the helper URL. + func completeWebRegistration(using credentials: WebRegistrationCredentials) async -> Result } // MARK: - OIDC diff --git a/ElementX/Sources/Services/Authentication/MockAuthenticationService.swift b/ElementX/Sources/Services/Authentication/MockAuthenticationService.swift new file mode 100644 index 0000000000..3cd72631ae --- /dev/null +++ b/ElementX/Sources/Services/Authentication/MockAuthenticationService.swift @@ -0,0 +1,65 @@ +// +// 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 Foundation +import MatrixRustSDK + +class MockAuthenticationService: AuthenticationServiceProtocol { + let validCredentials = (username: "alice", password: "12345678") + + private let homeserverSubject: CurrentValueSubject + var homeserver: CurrentValuePublisher { homeserverSubject.asCurrentValuePublisher() } + + init(homeserver: LoginHomeserver = .mockMatrixDotOrg) { + homeserverSubject = .init(homeserver) + } + + func configure(for homeserverAddress: String) async -> Result { + // Map the address to the mock homeservers + if LoginHomeserver.mockMatrixDotOrg.address.contains(homeserverAddress) { + homeserverSubject.send(.mockMatrixDotOrg) + return .success(()) + } else if LoginHomeserver.mockOIDC.address.contains(homeserverAddress) { + homeserverSubject.send(.mockOIDC) + return .success(()) + } else if LoginHomeserver.mockBasicServer.address.contains(homeserverAddress) { + homeserverSubject.send(.mockBasicServer) + return .success(()) + } else if LoginHomeserver.mockUnsupported.address.contains(homeserverAddress) { + homeserverSubject.send(.mockUnsupported) + return .success(()) + } else { + // Otherwise fail with an invalid server. + return .failure(.invalidServer) + } + } + + func urlForOIDCLogin() async -> Result { + .failure(.oidcError(.notSupported)) + } + + func abortOIDCLogin(data: OIDCAuthorizationDataProxy) async { } + + func loginWithOIDCCallback(_ callbackURL: URL, data: OIDCAuthorizationDataProxy) async -> Result { + .failure(.oidcError(.notSupported)) + } + + func login(username: String, password: String, initialDeviceName: String?, deviceID: String?) async -> Result { + // Login only succeeds if the username and password match the valid credentials property + guard username == validCredentials.username, password == validCredentials.password else { + return .failure(.invalidCredentials) + } + + let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: username)))) + return .success(userSession) + } + + func completeWebRegistration(using credentials: WebRegistrationCredentials) async -> Result { + .failure(.failedLoggingIn) + } +} diff --git a/ElementX/Sources/Services/Authentication/MockAuthenticationServiceProxy.swift b/ElementX/Sources/Services/Authentication/MockAuthenticationServiceProxy.swift deleted file mode 100644 index 5f2f49e170..0000000000 --- a/ElementX/Sources/Services/Authentication/MockAuthenticationServiceProxy.swift +++ /dev/null @@ -1,70 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Combine -import Foundation -import MatrixRustSDK - -class MockAuthenticationServiceProxy: AuthenticationServiceProtocol { - let validCredentials = (username: "alice", password: "12345678") - - private let homeserverSubject: CurrentValueSubject - var homeserver: CurrentValuePublisher { homeserverSubject.asCurrentValuePublisher() } - - init(homeserver: LoginHomeserver = .mockMatrixDotOrg) { - homeserverSubject = .init(homeserver) - } - - func configure(for homeserverAddress: String) async -> Result { - // Map the address to the mock homeservers - if LoginHomeserver.mockMatrixDotOrg.address.contains(homeserverAddress) { - homeserverSubject.send(.mockMatrixDotOrg) - return .success(()) - } else if LoginHomeserver.mockOIDC.address.contains(homeserverAddress) { - homeserverSubject.send(.mockOIDC) - return .success(()) - } else if LoginHomeserver.mockBasicServer.address.contains(homeserverAddress) { - homeserverSubject.send(.mockBasicServer) - return .success(()) - } else if LoginHomeserver.mockUnsupported.address.contains(homeserverAddress) { - homeserverSubject.send(.mockUnsupported) - return .success(()) - } else { - // Otherwise fail with an invalid server. - return .failure(.invalidServer) - } - } - - func urlForOIDCLogin() async -> Result { - .failure(.oidcError(.notSupported)) - } - - func abortOIDCLogin(data: OIDCAuthorizationDataProxy) async { } - - func loginWithOIDCCallback(_ callbackURL: URL, data: OIDCAuthorizationDataProxy) async -> Result { - .failure(.oidcError(.notSupported)) - } - - func login(username: String, password: String, initialDeviceName: String?, deviceID: String?) async -> Result { - // Login only succeeds if the username and password match the valid credentials property - guard username == validCredentials.username, password == validCredentials.password else { - return .failure(.invalidCredentials) - } - - let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: username)))) - return .success(userSession) - } -} diff --git a/ElementX/Sources/Services/Authentication/OIDCConfigurationProxy.swift b/ElementX/Sources/Services/Authentication/OIDCConfigurationProxy.swift index 8a0e1efd2b..484d191cc7 100644 --- a/ElementX/Sources/Services/Authentication/OIDCConfigurationProxy.swift +++ b/ElementX/Sources/Services/Authentication/OIDCConfigurationProxy.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/BugReport/BugReportService.swift b/ElementX/Sources/Services/BugReport/BugReportService.swift index de08a6ed7f..f263f653fb 100644 --- a/ElementX/Sources/Services/BugReport/BugReportService.swift +++ b/ElementX/Sources/Services/BugReport/BugReportService.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Services/BugReport/BugReportServiceProtocol.swift b/ElementX/Sources/Services/BugReport/BugReportServiceProtocol.swift index 1a4fd8390f..44baedb393 100644 --- a/ElementX/Sources/Services/BugReport/BugReportServiceProtocol.swift +++ b/ElementX/Sources/Services/BugReport/BugReportServiceProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Services/Client/Client.swift b/ElementX/Sources/Services/Client/Client.swift new file mode 100644 index 0000000000..d149c6aea9 --- /dev/null +++ b/ElementX/Sources/Services/Client/Client.swift @@ -0,0 +1,32 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Foundation +import MatrixRustSDK + +extension ClientProtocol { + func getElementWellKnown() async -> Result { + do { + let serverName = if let userIDServerName = try? userIdServerName() { + "https://\(userIDServerName)" + } else { + server() + } + + guard let serverName, + let url = URL(string: serverName)?.appending(path: "/.well-known/element/element.json") else { + return .failure(.invalidServerName) + } + + let response = try await getUrl(url: url.absoluteString) + let wellKnown = try makeElementWellKnown(string: response) + return .success(wellKnown) + } catch { + return .failure(.sdkError(error)) + } + } +} diff --git a/ElementX/Sources/Services/Client/ClientError.swift b/ElementX/Sources/Services/Client/ClientError.swift index c7d9dcfe85..25d4603796 100644 --- a/ElementX/Sources/Services/Client/ClientError.swift +++ b/ElementX/Sources/Services/Client/ClientError.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -34,12 +25,4 @@ extension ClientError { return first } - - /// Whether or not the error is related to the sliding sync proxy being full. - /// - /// This is a temporary error whilst we scale the backend infrastructure. - var isElementWaitlist: Bool { - guard case let .Generic(message) = self else { return false } - return message.contains("IO_ELEMENT_X_WAIT_LIST") - } } diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index a44da83625..b06c3e0cee 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -121,6 +112,8 @@ class ClientProxy: ClientProxyProtocol { verificationStateSubject.asCurrentValuePublisher() } + var roomsToAwait: Set = [] + private let sendQueueStatusSubject = CurrentValueSubject(false) init(client: ClientProtocol, @@ -210,6 +203,20 @@ class ClientProxy: ClientProxyProtocol { client.homeserver() } + var slidingSyncVersion: SlidingSyncVersion { + client.slidingSyncVersion() + } + + var availableSlidingSyncVersions: [SlidingSyncVersion] { + get async { + await client.availableSlidingSyncVersions() + } + } + + var canDeactivateAccount: Bool { + client.canDeactivateAccount() + } + var userIDServerName: String? { do { return try client.userIdServerName() @@ -347,8 +354,11 @@ class ClientProxy: ClientProxyProtocol { invite: [userID], avatar: nil, powerLevelContentOverride: Self.roomCreationPowerLevelOverrides) - let result = try await client.createRoom(request: parameters) - return await waitForRoomSummary(with: .success(result), name: expectedRoomName) + let roomID = try await client.createRoom(request: parameters) + + await waitForRoomToSync(roomID: roomID) + + return .success(roomID) } catch { MXLog.error("Failed creating direct room for userID: \(userID) with error: \(error)") return .failure(.sdkError(error)) @@ -367,7 +377,10 @@ class ClientProxy: ClientProxyProtocol { avatar: avatarURL?.absoluteString, powerLevelContentOverride: Self.roomCreationPowerLevelOverrides) let roomID = try await client.createRoom(request: parameters) - return await waitForRoomSummary(with: .success(roomID), name: name) + + await waitForRoomToSync(roomID: roomID) + + return .success(roomID) } catch { MXLog.error("Failed creating room with error: \(error)") return .failure(.sdkError(error)) @@ -377,9 +390,8 @@ class ClientProxy: ClientProxyProtocol { func joinRoom(_ roomID: String, via: [String]) async -> Result { do { let _ = try await client.joinRoomByIdOrAlias(roomIdOrAlias: roomID, serverNames: via) - - // Wait for the room to appear in the room lists to avoid issues downstream - let _ = await waitForRoomSummary(with: .success(roomID), name: nil, timeout: 30) + + await waitForRoomToSync(roomID: roomID, timeout: .seconds(30)) return .success(()) } catch { @@ -392,8 +404,7 @@ class ClientProxy: ClientProxyProtocol { do { let room = try await client.joinRoomByIdOrAlias(roomIdOrAlias: roomAlias, serverNames: []) - // Wait for the room to appear in the room lists to avoid issues downstream - let _ = await waitForRoomSummary(with: .success(room.id()), name: nil, timeout: 30) + await waitForRoomToSync(roomID: room.id(), timeout: .seconds(30)) return .success(()) } catch { @@ -420,46 +431,16 @@ class ClientProxy: ClientProxyProtocol { return .failure(ClientProxyError.sdkError(error)) } } - - /// Await the room to be available in the room summary list - private func waitForRoomSummary(with result: Result, name: String?, timeout: Int = 10) async -> Result { - guard case .success(let roomID) = result else { return result } - let runner = ExpiringTaskRunner { [weak self] in - guard let roomLists = self?.roomSummaryProvider?.roomListPublisher.values else { - return - } - // for every list of summaries, we check if we have a room summary with matching ID and name (if present) - for await roomList in roomLists { - guard let summary = roomList.first(where: { $0.id == roomID }) else { continue } - guard let name else { break } - if summary.name == name { - break - } - } - } - // we want to ignore the timeout error, and return the .success case because the room was properly created/joined already, we are only waiting for it to appear - try? await runner.run(timeout: .seconds(timeout)) - return result - } - - func roomForIdentifier(_ identifier: String) async -> RoomProxyProtocol? { - guard let roomListService else { - MXLog.error("Failed retrieving room, room list service not set up") - return nil - } + func roomForIdentifier(_ identifier: String) async -> RoomProxyType? { + let shouldAwait = roomsToAwait.remove(identifier) != nil // Try fetching the room from the cold cache (if available) first - var (roomListItem, room) = await roomTupleForIdentifier(identifier) - - if let roomListItem, let room { - return await RoomProxy(roomListService: roomListService, - roomListItem: roomListItem, - room: room) + if let room = await buildRoomForIdentifier(identifier) { + return room } // Else wait for the visible rooms list to go into fully loaded - guard let roomSummaryProvider else { MXLog.error("Rooms summary provider not setup yet") return nil @@ -469,21 +450,11 @@ class ClientProxy: ClientProxyProtocol { _ = await roomSummaryProvider.statePublisher.values.first(where: { $0.isLoaded }) } - (roomListItem, room) = await roomTupleForIdentifier(identifier) - - guard let roomListItem else { - MXLog.error("Invalid roomListItem for identifier \(identifier)") - return nil - } - - guard let room else { - MXLog.error("Invalid roomListItem fullRoom for identifier \(identifier)") - return nil + if shouldAwait { + await waitForRoomToSync(roomID: identifier) } - return await RoomProxy(roomListService: roomListService, - roomListItem: roomListItem, - room: room) + return await buildRoomForIdentifier(identifier) } func roomPreviewForIdentifier(_ identifier: String, via: [String]) async -> Result { @@ -585,6 +556,16 @@ class ClientProxy: ClientProxyProtocol { } } + func deactivateAccount(password: String?, eraseData: Bool) async -> Result { + do { + try await client.deactivateAccount(authData: password.map { .password(passwordDetails: .init(identifier: userID, password: $0)) }, + eraseData: eraseData) + return .success(()) + } catch { + return .failure(.sdkError(error)) + } + } + func setPusher(with configuration: PusherConfiguration) async throws { try await client.setPusher(identifiers: configuration.identifiers, kind: configuration.kind, @@ -633,20 +614,7 @@ class ClientProxy: ClientProxyProtocol { } func getElementWellKnown() async -> Result { - guard let userIDServerName, - var url = URL(string: "https://\(userIDServerName)") else { - return .failure(.invalidUserIDServerName) - } - - url.append(path: "/.well-known/element/element.json") - - do { - let response = try await client.getUrl(url: url.absoluteString) - let sdkWellKnown = try makeElementWellKnown(string: response) - return .success(ElementWellKnown(sdkWellKnown)) - } catch { - return .failure(.sdkError(error)) - } + await client.getElementWellKnown().map(ElementWellKnown.init) } // MARK: Ignored users @@ -703,9 +671,9 @@ class ClientProxy: ClientProxyProtocol { var users: OrderedSet = [] for roomID in roomIdentifiers { - guard let room = await roomForIdentifier(roomID), - room.isDirect, - let members = await room.members() else { + guard case let .joined(roomProxy) = await roomForIdentifier(roomID), + roomProxy.isDirect, + let members = await roomProxy.members() else { continue } @@ -816,9 +784,11 @@ class ClientProxy: ClientProxyProtocol { private func createRoomListServiceObserver(_ roomListService: RoomListService) -> TaskHandle { roomListService.state(listener: RoomListStateListenerProxy { [weak self] state in + guard let self else { return } + MXLog.info("Received room list update: \(state)") - guard let self, - state != .error, + + guard state != .error, state != .terminated else { // The sync service is responsible of handling error and termination return @@ -868,22 +838,47 @@ class ClientProxy: ClientProxyProtocol { return .exclude(eventTypes: stateEventFilters.map { FilterTimelineEventType.state(eventType: $0) }) }() - - private func roomTupleForIdentifier(_ identifier: String) async -> (RoomListItem?, Room?) { + + private func buildRoomForIdentifier(_ roomID: String) async -> RoomProxyType? { + guard let roomListService else { + MXLog.error("Failed retrieving room: \(roomID), room list service not set up") + return nil + } + do { - let roomListItem = try roomListService?.room(roomId: identifier) - if roomListItem?.isTimelineInitialized() == false { - try await roomListItem?.initTimeline(eventTypeFilter: eventFilters, internalIdPrefix: nil) - } - let fullRoom = try roomListItem?.fullRoom() + let roomListItem = try roomListService.room(roomId: roomID) - return (roomListItem, fullRoom) + switch roomListItem.membership() { + case .invited: + return try .invited(InvitedRoomProxy(roomListItem: roomListItem, + room: roomListItem.invitedRoom())) + case .joined: + if roomListItem.isTimelineInitialized() == false { + try await roomListItem.initTimeline(eventTypeFilter: eventFilters, internalIdPrefix: nil) + } + + let roomProxy = try await JoinedRoomProxy(roomListService: roomListService, + roomListItem: roomListItem, + room: roomListItem.fullRoom()) + + return .joined(roomProxy) + case .left: + return .left + } } catch { - MXLog.error("Failed retrieving/initialising room with identifier: \(identifier)") - return (nil, nil) + MXLog.error("Failed retrieving room: \(roomID), with error: \(error)") + return nil } } + private func waitForRoomToSync(roomID: String, timeout: Duration = .seconds(10)) async { + let runner = ExpiringTaskRunner { [weak self] in + try await self?.client.awaitRoomRemoteEcho(roomId: roomID) + } + + _ = try? await runner.run(timeout: timeout) + } + private func updateIgnoredUsers() { Task { do { diff --git a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift index 62785e59fc..29a5a856cb 100644 --- a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift +++ b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -41,7 +32,7 @@ enum ClientProxyError: Error { case sdkError(Error) case invalidMedia - case invalidUserIDServerName + case invalidServerName case failedUploadingMedia(Error, MatrixErrorCode) case roomPreviewIsPrivate } @@ -54,7 +45,8 @@ enum SlidingSyncConstants { RequiredState(key: "m.room.topic", value: ""), RequiredState(key: "m.room.avatar", value: ""), RequiredState(key: "m.room.canonical_alias", value: ""), - RequiredState(key: "m.room.join_rules", value: "") + RequiredState(key: "m.room.join_rules", value: ""), + RequiredState(key: "m.room.pinned_events", value: "") ] } @@ -104,8 +96,13 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol { var homeserver: String { get } + var slidingSyncVersion: SlidingSyncVersion { get } + var availableSlidingSyncVersions: [SlidingSyncVersion] { get async } + + var canDeactivateAccount: Bool { get } + var userIDServerName: String? { get } - + var userDisplayNamePublisher: CurrentValuePublisher { get } var userAvatarURLPublisher: CurrentValuePublisher { get } @@ -117,6 +114,8 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol { var roomSummaryProvider: RoomSummaryProviderProtocol? { get } + var roomsToAwait: Set { get set } + /// Used for listing rooms that shouldn't be affected by the main `roomSummaryProvider` filtering var alternateRoomSummaryProvider: RoomSummaryProviderProtocol? { get } @@ -146,7 +145,7 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol { func uploadMedia(_ media: MediaInfo) async -> Result - func roomForIdentifier(_ identifier: String) async -> RoomProxyProtocol? + func roomForIdentifier(_ identifier: String) async -> RoomProxyType? func roomPreviewForIdentifier(_ identifier: String, via: [String]) async -> Result @@ -162,6 +161,8 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol { func sessionVerificationControllerProxy() async -> Result + func deactivateAccount(password: String?, eraseData: Bool) async -> Result + func logout() async -> URL? func setPusher(with configuration: PusherConfiguration) async throws diff --git a/ElementX/Sources/Services/Client/ElementWellKnown.swift b/ElementX/Sources/Services/Client/ElementWellKnown.swift index c65e0090b2..187d742342 100644 --- a/ElementX/Sources/Services/Client/ElementWellKnown.swift +++ b/ElementX/Sources/Services/Client/ElementWellKnown.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -28,8 +19,10 @@ struct ElementWellKnown { } let call: Call? + let registrationHelperURL: URL? init?(_ wellKnown: MatrixRustSDK.ElementWellKnown) { - call = Call(wellKnown.call) + call = wellKnown.call.flatMap(Call.init) + registrationHelperURL = wellKnown.registrationHelperUrl.flatMap(URL.init) } } diff --git a/ElementX/Sources/Services/ComposerDraft/ComposerDraftService.swift b/ElementX/Sources/Services/ComposerDraft/ComposerDraftService.swift index 615d344e1f..b27253420d 100644 --- a/ElementX/Sources/Services/ComposerDraft/ComposerDraftService.swift +++ b/ElementX/Sources/Services/ComposerDraft/ComposerDraftService.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -19,11 +10,11 @@ import Foundation import MatrixRustSDK final class ComposerDraftService: ComposerDraftServiceProtocol { - private let roomProxy: RoomProxyProtocol + private let roomProxy: JoinedRoomProxyProtocol private let timelineItemfactory: RoomTimelineItemFactoryProtocol private var volatileDraft: ComposerDraftProxy? - init(roomProxy: RoomProxyProtocol, timelineItemfactory: RoomTimelineItemFactoryProtocol) { + init(roomProxy: JoinedRoomProxyProtocol, timelineItemfactory: RoomTimelineItemFactoryProtocol) { self.roomProxy = roomProxy self.timelineItemfactory = timelineItemfactory } diff --git a/ElementX/Sources/Services/ComposerDraft/ComposerDraftServiceProtocol.swift b/ElementX/Sources/Services/ComposerDraft/ComposerDraftServiceProtocol.swift index 84109fdeb9..be8f16ffa7 100644 --- a/ElementX/Sources/Services/ComposerDraft/ComposerDraftServiceProtocol.swift +++ b/ElementX/Sources/Services/ComposerDraft/ComposerDraftServiceProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/CreateRoom/CreateRoomFlowParameters.swift b/ElementX/Sources/Services/CreateRoom/CreateRoomFlowParameters.swift index 4639534de8..d61a7e79ea 100644 --- a/ElementX/Sources/Services/CreateRoom/CreateRoomFlowParameters.swift +++ b/ElementX/Sources/Services/CreateRoom/CreateRoomFlowParameters.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/ElementCall/ElementCallConfiguration.swift b/ElementX/Sources/Services/ElementCall/ElementCallConfiguration.swift new file mode 100644 index 0000000000..31da3bb16f --- /dev/null +++ b/ElementX/Sources/Services/ElementCall/ElementCallConfiguration.swift @@ -0,0 +1,79 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import SwiftUI + +private enum GenericCallLinkQueryParameters { + static let appPrompt = "appPrompt" + static let confineToRoom = "confineToRoom" +} + +/// Information about how a call should be configured. +struct ElementCallConfiguration { + enum Kind { + case genericCallLink(URL) + case roomCall(roomProxy: JoinedRoomProxyProtocol, + clientProxy: ClientProxyProtocol, + clientID: String, + elementCallBaseURL: URL, + elementCallBaseURLOverride: URL?, + colorScheme: ColorScheme) + } + + /// The type of call being configured i.e. whether it's an external URL or an internal room call. + let kind: Kind + + /// Creates a configuration for an external call URL. + init(genericCallLink url: URL) { + if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true) { + var fragmentQueryItems = urlComponents.fragmentQueryItems ?? [] + + fragmentQueryItems.removeAll { $0.name == GenericCallLinkQueryParameters.appPrompt } + fragmentQueryItems.removeAll { $0.name == GenericCallLinkQueryParameters.confineToRoom } + + fragmentQueryItems.append(.init(name: GenericCallLinkQueryParameters.appPrompt, value: "false")) + fragmentQueryItems.append(.init(name: GenericCallLinkQueryParameters.confineToRoom, value: "true")) + + urlComponents.fragmentQueryItems = fragmentQueryItems + + if let adjustedURL = urlComponents.url { + kind = .genericCallLink(adjustedURL) + } else { + MXLog.error("Failed adjusting URL with components: \(urlComponents)") + kind = .genericCallLink(url) + } + } else { + MXLog.error("Failed constructing URL components for url: \(url)") + kind = .genericCallLink(url) + } + } + + /// Creates a configuration for an internal room call. + init(roomProxy: JoinedRoomProxyProtocol, + clientProxy: ClientProxyProtocol, + clientID: String, + elementCallBaseURL: URL, + elementCallBaseURLOverride: URL?, + colorScheme: ColorScheme) { + kind = .roomCall(roomProxy: roomProxy, + clientProxy: clientProxy, + clientID: clientID, + elementCallBaseURL: elementCallBaseURL, + elementCallBaseURLOverride: elementCallBaseURLOverride, + colorScheme: colorScheme) + } + + /// A string representing the call being configured. + var callRoomID: String { + switch kind { + case .genericCallLink(let url): + url.absoluteString + case .roomCall(let roomProxy, _, _, _, _, _): + roomProxy.id + } + } +} diff --git a/ElementX/Sources/Services/ElementCall/ElementCallService.swift b/ElementX/Sources/Services/ElementCall/ElementCallService.swift index 2390a3d0a8..980e9b5f3e 100644 --- a/ElementX/Sources/Services/ElementCall/ElementCallService.swift +++ b/ElementX/Sources/Services/ElementCall/ElementCallService.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import AVFoundation @@ -57,7 +48,14 @@ class ElementCallService: NSObject, ElementCallServiceProtocol, PKPushRegistryDe private var endUnansweredCallTask: Task? - private var ongoingCallID: CallID? + private var ongoingCallID: CallID? { + didSet { ongoingCallRoomIDSubject.send(ongoingCallID?.roomID) } + } + + let ongoingCallRoomIDSubject = CurrentValueSubject(nil) + var ongoingCallRoomIDPublisher: CurrentValuePublisher { + ongoingCallRoomIDSubject.asCurrentValuePublisher() + } private let actionsSubject: PassthroughSubject = .init() var actions: AnyPublisher { @@ -253,8 +251,6 @@ class ElementCallService: NSObject, ElementCallServiceProtocol, PKPushRegistryDe // MARK: - Private func tearDownCallSession(sendEndCallAction: Bool = true) { - try? AVAudioSession.sharedInstance().setActive(false) - if sendEndCallAction, let ongoingCallID { let transaction = CXTransaction(action: CXEndCallAction(call: ongoingCallID.callKitID)) callController.request(transaction) { error in @@ -274,7 +270,7 @@ class ElementCallService: NSObject, ElementCallServiceProtocol, PKPushRegistryDe return } - guard let roomProxy = await clientProxy.roomForIdentifier(incomingCallID.roomID) else { + guard case let .joined(roomProxy) = await clientProxy.roomForIdentifier(incomingCallID.roomID) else { return } diff --git a/ElementX/Sources/Services/ElementCall/ElementCallServiceConstants.swift b/ElementX/Sources/Services/ElementCall/ElementCallServiceConstants.swift index bec2dc85d2..2af2d2208b 100644 --- a/ElementX/Sources/Services/ElementCall/ElementCallServiceConstants.swift +++ b/ElementX/Sources/Services/ElementCall/ElementCallServiceConstants.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/ElementCall/ElementCallServiceProtocol.swift b/ElementX/Sources/Services/ElementCall/ElementCallServiceProtocol.swift index 1c47b23f0b..1247541e55 100644 --- a/ElementX/Sources/Services/ElementCall/ElementCallServiceProtocol.swift +++ b/ElementX/Sources/Services/ElementCall/ElementCallServiceProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -26,6 +17,8 @@ enum ElementCallServiceAction { protocol ElementCallServiceProtocol { var actions: AnyPublisher { get } + var ongoingCallRoomIDPublisher: CurrentValuePublisher { get } + func setClientProxy(_ clientProxy: ClientProxyProtocol) func setupCallSession(roomID: String, roomDisplayName: String) async diff --git a/ElementX/Sources/Services/ElementCall/ElementCallWidgetDriver.swift b/ElementX/Sources/Services/ElementCall/ElementCallWidgetDriver.swift index 6969bb1716..30a41e936f 100644 --- a/ElementX/Sources/Services/ElementCall/ElementCallWidgetDriver.swift +++ b/ElementX/Sources/Services/ElementCall/ElementCallWidgetDriver.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -147,7 +138,7 @@ class ElementCallWidgetDriver: WidgetCapabilitiesProvider, ElementCallWidgetDriv return .success(url) } - func sendMessage(_ message: String) async -> Result { + func handleMessage(_ message: String) async -> Result { guard let widgetDriver else { return .failure(.driverNotSetup) } diff --git a/ElementX/Sources/Services/ElementCall/ElementCallWidgetDriverProtocol.swift b/ElementX/Sources/Services/ElementCall/ElementCallWidgetDriverProtocol.swift index 1c512a921d..7ba61a2c35 100644 --- a/ElementX/Sources/Services/ElementCall/ElementCallWidgetDriverProtocol.swift +++ b/ElementX/Sources/Services/ElementCall/ElementCallWidgetDriverProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -40,5 +31,6 @@ protocol ElementCallWidgetDriverProtocol { func start(baseURL: URL, clientID: String, colorScheme: ColorScheme) async -> Result - func sendMessage(_ message: String) async -> Result + /// Passes a message from the Widget to the SDK to handle, returning a Bool that represents whether or not the widget driver is still running. + func handleMessage(_ message: String) async -> Result } diff --git a/ElementX/Sources/Services/ElementCall/GenericCallLinkWidgetDriver.swift b/ElementX/Sources/Services/ElementCall/GenericCallLinkWidgetDriver.swift new file mode 100644 index 0000000000..cab959b2bc --- /dev/null +++ b/ElementX/Sources/Services/ElementCall/GenericCallLinkWidgetDriver.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 SwiftUI + +class GenericCallLinkWidgetDriver: ElementCallWidgetDriverProtocol { + private let url: URL + + let widgetID = UUID().uuidString + let messagePublisher = PassthroughSubject() + + private let actionsSubject: PassthroughSubject = .init() + var actions: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + init(url: URL) { + self.url = url + } + + func start(baseURL: URL, clientID: String, colorScheme: ColorScheme) async -> Result { + MXLog.error("Nothing to start, use the configuration's URL directly instead.") + return .success(url) + } + + func handleMessage(_ message: String) async -> Result { + // The web view doesn't send us messages through the Widget API, so nothing to implement (yet?). + .failure(.driverNotSetup) + } +} diff --git a/ElementX/Sources/Services/Emojis/EmojiCategory.swift b/ElementX/Sources/Services/Emojis/EmojiCategory.swift index 6ae94eed08..7e42a1f819 100644 --- a/ElementX/Sources/Services/Emojis/EmojiCategory.swift +++ b/ElementX/Sources/Services/Emojis/EmojiCategory.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Emojis/EmojiItem.swift b/ElementX/Sources/Services/Emojis/EmojiItem.swift index 3b8abce702..d08cbb0abf 100644 --- a/ElementX/Sources/Services/Emojis/EmojiItem.swift +++ b/ElementX/Sources/Services/Emojis/EmojiItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Emojis/EmojiLoaderProtocol.swift b/ElementX/Sources/Services/Emojis/EmojiLoaderProtocol.swift index 9df9c3eb91..6923367e54 100644 --- a/ElementX/Sources/Services/Emojis/EmojiLoaderProtocol.swift +++ b/ElementX/Sources/Services/Emojis/EmojiLoaderProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Emojis/EmojiProvider.swift b/ElementX/Sources/Services/Emojis/EmojiProvider.swift index 5609584e2d..5272902183 100644 --- a/ElementX/Sources/Services/Emojis/EmojiProvider.swift +++ b/ElementX/Sources/Services/Emojis/EmojiProvider.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Emojibase diff --git a/ElementX/Sources/Services/Keychain/EncryptionKeyProvider.swift b/ElementX/Sources/Services/Keychain/EncryptionKeyProvider.swift index e31d06eb5e..845bdbe896 100644 --- a/ElementX/Sources/Services/Keychain/EncryptionKeyProvider.swift +++ b/ElementX/Sources/Services/Keychain/EncryptionKeyProvider.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import CryptoKit diff --git a/ElementX/Sources/Services/Keychain/EncryptionKeyProviderProtocol.swift b/ElementX/Sources/Services/Keychain/EncryptionKeyProviderProtocol.swift index 0437578562..96f5cb5b5a 100644 --- a/ElementX/Sources/Services/Keychain/EncryptionKeyProviderProtocol.swift +++ b/ElementX/Sources/Services/Keychain/EncryptionKeyProviderProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Keychain/KeychainController.swift b/ElementX/Sources/Services/Keychain/KeychainController.swift index b95f534638..ba11719849 100644 --- a/ElementX/Sources/Services/Keychain/KeychainController.swift +++ b/ElementX/Sources/Services/Keychain/KeychainController.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -119,7 +110,7 @@ class KeychainController: KeychainControllerProtocol { fatalError("Something has gone mega wrong, all bets are off.") } let restorationToken = RestorationToken(session: session, - sessionDirectory: oldToken.sessionDirectory, + sessionDirectories: oldToken.sessionDirectories, passphrase: oldToken.passphrase, pusherNotificationClientIdentifier: oldToken.pusherNotificationClientIdentifier) setRestorationToken(restorationToken, forUsername: session.userId) diff --git a/ElementX/Sources/Services/Keychain/KeychainControllerMock.swift b/ElementX/Sources/Services/Keychain/KeychainControllerMock.swift index e15947427e..52402af8f0 100644 --- a/ElementX/Sources/Services/Keychain/KeychainControllerMock.swift +++ b/ElementX/Sources/Services/Keychain/KeychainControllerMock.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import MatrixRustSDK diff --git a/ElementX/Sources/Services/Keychain/KeychainControllerProtocol.swift b/ElementX/Sources/Services/Keychain/KeychainControllerProtocol.swift index c90fd55c05..70e76a417f 100644 --- a/ElementX/Sources/Services/Keychain/KeychainControllerProtocol.swift +++ b/ElementX/Sources/Services/Keychain/KeychainControllerProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Media/MediaUploadingPreprocessor.swift b/ElementX/Sources/Services/Media/MediaUploadingPreprocessor.swift index f6140936be..cec36f19c7 100644 --- a/ElementX/Sources/Services/Media/MediaUploadingPreprocessor.swift +++ b/ElementX/Sources/Services/Media/MediaUploadingPreprocessor.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import AVFoundation @@ -86,7 +77,7 @@ private struct VideoProcessingInfo { let url: URL let height: Double let width: Double - let duration: Double + let duration: Double // seconds let mimeType: String } @@ -222,7 +213,7 @@ struct MediaUploadingPreprocessor { return .failure(.failedProcessingAudio) } - let audioInfo = AudioInfo(duration: durationInSeconds * 1000, size: fileSize, mimetype: mimeType) + let audioInfo = AudioInfo(duration: durationInSeconds, size: fileSize, mimetype: mimeType) return .success(.audio(audioURL: url, audioInfo: audioInfo)) } @@ -422,7 +413,7 @@ struct MediaUploadingPreprocessor { return .success(.init(url: newOutputURL, height: adjustedNaturalSize.height, width: adjustedNaturalSize.width, - duration: durationInSeconds * 1000, + duration: durationInSeconds, mimeType: "video/mp4")) } catch { return .failure(.failedConvertingVideo) diff --git a/ElementX/Sources/Services/Media/Provider/ImageProviderProtocol.swift b/ElementX/Sources/Services/Media/Provider/ImageProviderProtocol.swift deleted file mode 100644 index 345726106a..0000000000 --- a/ElementX/Sources/Services/Media/Provider/ImageProviderProtocol.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright 2023 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import UIKit - -protocol ImageProviderProtocol { - func imageFromSource(_ source: MediaSourceProxy?, size: CGSize?) -> UIImage? - - func loadImageFromSource(_ source: MediaSourceProxy, size: CGSize?) async -> Result - - func loadImageDataFromSource(_ source: MediaSourceProxy) async -> Result -} - -extension ImageProviderProtocol { - func imageFromSource(_ source: MediaSourceProxy?) -> UIImage? { - imageFromSource(source, size: nil) - } -} diff --git a/ElementX/Sources/Services/Media/Provider/MediaFileHandleProxy.swift b/ElementX/Sources/Services/Media/Provider/MediaFileHandleProxy.swift index 00fe7f4105..ba5a746f51 100644 --- a/ElementX/Sources/Services/Media/Provider/MediaFileHandleProxy.swift +++ b/ElementX/Sources/Services/Media/Provider/MediaFileHandleProxy.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Media/Provider/MediaLoader.swift b/ElementX/Sources/Services/Media/Provider/MediaLoader.swift index 651c948aac..427aeb77c5 100644 --- a/ElementX/Sources/Services/Media/Provider/MediaLoader.swift +++ b/ElementX/Sources/Services/Media/Provider/MediaLoader.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Services/Media/Provider/MediaLoaderProtocol.swift b/ElementX/Sources/Services/Media/Provider/MediaLoaderProtocol.swift index a620c19750..a19ef95a81 100644 --- a/ElementX/Sources/Services/Media/Provider/MediaLoaderProtocol.swift +++ b/ElementX/Sources/Services/Media/Provider/MediaLoaderProtocol.swift @@ -1,21 +1,13 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation +// sourcery: AutoMockable protocol MediaLoaderProtocol { func loadMediaContentForSource(_ source: MediaSourceProxy) async throws -> Data diff --git a/ElementX/Sources/Services/Media/Provider/MediaProvider.swift b/ElementX/Sources/Services/Media/Provider/MediaProvider.swift index 55877f2a49..b87f42603e 100644 --- a/ElementX/Sources/Services/Media/Provider/MediaProvider.swift +++ b/ElementX/Sources/Services/Media/Provider/MediaProvider.swift @@ -1,30 +1,25 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // +import Combine import Kingfisher import UIKit struct MediaProvider: MediaProviderProtocol { private let mediaLoader: MediaLoaderProtocol private let imageCache: Kingfisher.ImageCache + private let networkMonitor: NetworkMonitorProtocol? init(mediaLoader: MediaLoaderProtocol, - imageCache: Kingfisher.ImageCache) { + imageCache: Kingfisher.ImageCache, + networkMonitor: NetworkMonitorProtocol?) { self.mediaLoader = mediaLoader self.imageCache = imageCache + self.networkMonitor = networkMonitor } // MARK: Images @@ -71,6 +66,45 @@ struct MediaProvider: MediaProviderProtocol { } } + func loadImageRetryingOnReconnection(_ source: MediaSourceProxy, size: CGSize?) -> Task { + guard let networkMonitor else { + fatalError("This method shouldn't be invoked without a NetworkMonitor set.") + } + + return Task { + if case let .success(image) = await loadImageFromSource(source, size: size) { + return image + } + + guard !Task.isCancelled else { + throw MediaProviderError.cancelled + } + + for await reachability in networkMonitor.reachabilityPublisher.values { + guard !Task.isCancelled else { + throw MediaProviderError.cancelled + } + + guard reachability == .reachable else { + continue + } + + switch await loadImageFromSource(source, size: size) { + case .success(let image): + return image + case .failure: + // If it fails after a retry with the network available + // then something else must be wrong. Bail out. + if reachability == .reachable { + throw MediaProviderError.cancelled + } + } + } + + throw MediaProviderError.cancelled + } + } + func loadImageDataFromSource(_ source: MediaSourceProxy) async -> Result { do { let imageData = try await mediaLoader.loadMediaContentForSource(source) diff --git a/ElementX/Sources/Services/Media/Provider/MediaProviderProtocol.swift b/ElementX/Sources/Services/Media/Provider/MediaProviderProtocol.swift index 2bc47764d8..7306b458e7 100644 --- a/ElementX/Sources/Services/Media/Provider/MediaProviderProtocol.swift +++ b/ElementX/Sources/Services/Media/Provider/MediaProviderProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -22,14 +13,29 @@ enum MediaProviderError: Error { case failedRetrievingFile case invalidImageData case failedRetrievingThumbnail + case cancelled } -protocol MediaProviderProtocol: ImageProviderProtocol { - func loadFileFromSource(_ source: MediaSourceProxy, body: String?) async -> Result +protocol MediaProviderProtocol { + func imageFromSource(_ source: MediaSourceProxy?, size: CGSize?) -> UIImage? + func loadImageFromSource(_ source: MediaSourceProxy, size: CGSize?) async -> Result + func loadImageDataFromSource(_ source: MediaSourceProxy) async -> Result + func loadImageRetryingOnReconnection(_ source: MediaSourceProxy, size: CGSize?) -> Task + func loadThumbnailForSource(source: MediaSourceProxy, size: CGSize) async -> Result + + func loadFileFromSource(_ source: MediaSourceProxy, body: String?) async -> Result } extension MediaProviderProtocol { + func imageFromSource(_ source: MediaSourceProxy?) -> UIImage? { + imageFromSource(source, size: nil) + } + + func loadImageRetryingOnReconnection(_ source: MediaSourceProxy) -> Task { + loadImageRetryingOnReconnection(source, size: nil) + } + func loadFileFromSource(_ source: MediaSourceProxy) async -> Result { await loadFileFromSource(source, body: nil) } diff --git a/ElementX/Sources/Services/Media/Provider/MediaSourceProxy.swift b/ElementX/Sources/Services/Media/Provider/MediaSourceProxy.swift index 9c47b2e967..abfb3b2fee 100644 --- a/ElementX/Sources/Services/Media/Provider/MediaSourceProxy.swift +++ b/ElementX/Sources/Services/Media/Provider/MediaSourceProxy.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Media/Provider/MockMediaProvider.swift b/ElementX/Sources/Services/Media/Provider/MockMediaProvider.swift index 63064a2478..3a77954da2 100644 --- a/ElementX/Sources/Services/Media/Provider/MockMediaProvider.swift +++ b/ElementX/Sources/Services/Media/Provider/MockMediaProvider.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -58,4 +49,14 @@ struct MockMediaProvider: MediaProviderProtocol { } return .failure(.failedRetrievingFile) } + + func loadImageRetryingOnReconnection(_ source: MediaSourceProxy, size: CGSize?) -> Task { + Task { + guard let image = UIImage(systemName: "photo") else { + fatalError() + } + + return image + } + } } diff --git a/ElementX/Sources/Services/MediaPlayer/MediaPlayerProtocol.swift b/ElementX/Sources/Services/MediaPlayer/MediaPlayerProtocol.swift index 2666d19af3..e955061139 100644 --- a/ElementX/Sources/Services/MediaPlayer/MediaPlayerProtocol.swift +++ b/ElementX/Sources/Services/MediaPlayer/MediaPlayerProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/MediaPlayer/MediaPlayerProvider.swift b/ElementX/Sources/Services/MediaPlayer/MediaPlayerProvider.swift index ca890bd1b5..894269cc56 100644 --- a/ElementX/Sources/Services/MediaPlayer/MediaPlayerProvider.swift +++ b/ElementX/Sources/Services/MediaPlayer/MediaPlayerProvider.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/MediaPlayer/MediaPlayerProviderProtocol.swift b/ElementX/Sources/Services/MediaPlayer/MediaPlayerProviderProtocol.swift index e32e44a2b0..c1cb2b74ee 100644 --- a/ElementX/Sources/Services/MediaPlayer/MediaPlayerProviderProtocol.swift +++ b/ElementX/Sources/Services/MediaPlayer/MediaPlayerProviderProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Notification/Manager/APNSPayload.swift b/ElementX/Sources/Services/Notification/Manager/APNSPayload.swift index 9ff9666027..c876d140a0 100644 --- a/ElementX/Sources/Services/Notification/Manager/APNSPayload.swift +++ b/ElementX/Sources/Services/Notification/Manager/APNSPayload.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Notification/Manager/NotificationManager.swift b/ElementX/Sources/Services/Notification/Manager/NotificationManager.swift index 060c594607..d5fd7f7eb0 100644 --- a/ElementX/Sources/Services/Notification/Manager/NotificationManager.swift +++ b/ElementX/Sources/Services/Notification/Manager/NotificationManager.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Services/Notification/Manager/NotificationManagerProtocol.swift b/ElementX/Sources/Services/Notification/Manager/NotificationManagerProtocol.swift index a88b937c29..273dcab85c 100644 --- a/ElementX/Sources/Services/Notification/Manager/NotificationManagerProtocol.swift +++ b/ElementX/Sources/Services/Notification/Manager/NotificationManagerProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Notification/Manager/UserNotificationCenterProtocol.swift b/ElementX/Sources/Services/Notification/Manager/UserNotificationCenterProtocol.swift index 615ec0a0dd..adab558790 100644 --- a/ElementX/Sources/Services/Notification/Manager/UserNotificationCenterProtocol.swift +++ b/ElementX/Sources/Services/Notification/Manager/UserNotificationCenterProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Notification/NotificationConstants.swift b/ElementX/Sources/Services/Notification/NotificationConstants.swift index b51d0db31f..322b0ab64f 100644 --- a/ElementX/Sources/Services/Notification/NotificationConstants.swift +++ b/ElementX/Sources/Services/Notification/NotificationConstants.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxy.swift b/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxy.swift index 7b9c2b16c0..40cbf1e8a9 100644 --- a/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxy.swift +++ b/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxy.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxyProtocol.swift b/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxyProtocol.swift index 947e59a7b7..cced638789 100644 --- a/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxyProtocol.swift +++ b/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxyProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/NotificationSettings/NotificationSettingsChatType.swift b/ElementX/Sources/Services/NotificationSettings/NotificationSettingsChatType.swift index 0063514b12..621feefe77 100644 --- a/ElementX/Sources/Services/NotificationSettings/NotificationSettingsChatType.swift +++ b/ElementX/Sources/Services/NotificationSettings/NotificationSettingsChatType.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/NotificationSettings/NotificationSettingsProxy.swift b/ElementX/Sources/Services/NotificationSettings/NotificationSettingsProxy.swift index f5245d03ff..0b8502ce31 100644 --- a/ElementX/Sources/Services/NotificationSettings/NotificationSettingsProxy.swift +++ b/ElementX/Sources/Services/NotificationSettings/NotificationSettingsProxy.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Services/NotificationSettings/NotificationSettingsProxyProtocol.swift b/ElementX/Sources/Services/NotificationSettings/NotificationSettingsProxyProtocol.swift index 91514222fc..c70e468bdb 100644 --- a/ElementX/Sources/Services/NotificationSettings/NotificationSettingsProxyProtocol.swift +++ b/ElementX/Sources/Services/NotificationSettings/NotificationSettingsProxyProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Services/NotificationSettings/RoomNotificationModeProxy.swift b/ElementX/Sources/Services/NotificationSettings/RoomNotificationModeProxy.swift index 6b3c0267cf..b6e8f7e312 100644 --- a/ElementX/Sources/Services/NotificationSettings/RoomNotificationModeProxy.swift +++ b/ElementX/Sources/Services/NotificationSettings/RoomNotificationModeProxy.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/NotificationSettings/RoomNotificationSettingsProxy.swift b/ElementX/Sources/Services/NotificationSettings/RoomNotificationSettingsProxy.swift index e449c4f87d..416defc933 100644 --- a/ElementX/Sources/Services/NotificationSettings/RoomNotificationSettingsProxy.swift +++ b/ElementX/Sources/Services/NotificationSettings/RoomNotificationSettingsProxy.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/NotificationSettings/RoomNotificationSettingsProxyProtocol.swift b/ElementX/Sources/Services/NotificationSettings/RoomNotificationSettingsProxyProtocol.swift index cddba1b09b..5f7f9bf7d7 100644 --- a/ElementX/Sources/Services/NotificationSettings/RoomNotificationSettingsProxyProtocol.swift +++ b/ElementX/Sources/Services/NotificationSettings/RoomNotificationSettingsProxyProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Polls/PollInteractionHandler.swift b/ElementX/Sources/Services/Polls/PollInteractionHandler.swift index 507043af9a..79d3ef38c0 100644 --- a/ElementX/Sources/Services/Polls/PollInteractionHandler.swift +++ b/ElementX/Sources/Services/Polls/PollInteractionHandler.swift @@ -1,26 +1,17 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation class PollInteractionHandler: PollInteractionHandlerProtocol { let analyticsService: AnalyticsService - let roomProxy: RoomProxyProtocol + let roomProxy: JoinedRoomProxyProtocol - init(analyticsService: AnalyticsService, roomProxy: RoomProxyProtocol) { + init(analyticsService: AnalyticsService, roomProxy: JoinedRoomProxyProtocol) { self.analyticsService = analyticsService self.roomProxy = roomProxy } diff --git a/ElementX/Sources/Services/Polls/PollInteractionHandlerProtocol.swift b/ElementX/Sources/Services/Polls/PollInteractionHandlerProtocol.swift index 9caa2bed18..eca6a0a918 100644 --- a/ElementX/Sources/Services/Polls/PollInteractionHandlerProtocol.swift +++ b/ElementX/Sources/Services/Polls/PollInteractionHandlerProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/QRCode/QRCodeLoginService.swift b/ElementX/Sources/Services/QRCode/QRCodeLoginService.swift index 85bf3efe10..015a6a9d09 100644 --- a/ElementX/Sources/Services/QRCode/QRCodeLoginService.swift +++ b/ElementX/Sources/Services/QRCode/QRCodeLoginService.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -20,7 +11,7 @@ import Foundation import MatrixRustSDK final class QRCodeLoginService: QRCodeLoginServiceProtocol { - private var sessionDirectory: URL + private var sessionDirectories: SessionDirectories private let passphrase: String private let userSessionStore: UserSessionStoreProtocol @@ -36,7 +27,7 @@ final class QRCodeLoginService: QRCodeLoginServiceProtocol { userSessionStore: UserSessionStoreProtocol, appSettings: AppSettings, appHooks: AppHooks) { - sessionDirectory = .sessionsBaseDirectory.appending(component: UUID().uuidString) + sessionDirectories = .init() passphrase = encryptionKeyProvider.generateKey().base64EncodedString() self.userSessionStore = userSessionStore self.appSettings = appSettings @@ -57,9 +48,10 @@ final class QRCodeLoginService: QRCodeLoginServiceProtocol { } do { - let client = try await makeClientBuilder().buildWithQrCode(qrCodeData: qrData, - oidcConfiguration: appSettings.oidcConfiguration.rustValue, + let client = try await makeClientBuilder().buildWithQRCode(qrCodeData: qrData, + oidcConfiguration: appSettings.oidcConfiguration, progressListener: listener) + MXLog.info("Sliding sync: \(client.slidingSyncVersion())") return await userSession(for: client) } catch let error as HumanQrLoginError { MXLog.error("QRCode login error: \(error)") @@ -72,31 +64,25 @@ final class QRCodeLoginService: QRCodeLoginServiceProtocol { // MARK: - Private - private func makeClientBuilder() -> ClientBuilder { + private func makeClientBuilder() -> AuthenticationClientBuilder { // Use a fresh session directory each time the user scans a QR code to ensure caches // (e.g. server versions) are always fresh in case a different server is used. rotateSessionDirectory() - return ClientBuilder - .baseBuilder(httpProxy: appSettings.websiteURL.globalProxy, - slidingSync: appSettings.simplifiedSlidingSyncEnabled ? .simplified : .discovered, - slidingSyncProxy: appSettings.slidingSyncProxyURL, - sessionDelegate: userSessionStore.clientSessionDelegate, - appHooks: appHooks) - .sessionPath(path: sessionDirectory.path(percentEncoded: false)) - .passphrase(passphrase: passphrase) + return AuthenticationClientBuilder(sessionDirectories: sessionDirectories, + passphrase: passphrase, + clientSessionDelegate: userSessionStore.clientSessionDelegate, + appSettings: appSettings, + appHooks: appHooks) } private func rotateSessionDirectory() { - if FileManager.default.directoryExists(at: sessionDirectory) { - try? FileManager.default.removeItem(at: sessionDirectory) - } - - sessionDirectory = .sessionsBaseDirectory.appending(component: UUID().uuidString) + sessionDirectories.delete() + sessionDirectories = .init() } private func userSession(for client: Client) async -> Result { - switch await userSessionStore.userSession(for: client, sessionDirectory: sessionDirectory, passphrase: passphrase) { + switch await userSessionStore.userSession(for: client, sessionDirectories: sessionDirectories, passphrase: passphrase) { case .success(let session): return .success(session) case .failure(let error): diff --git a/ElementX/Sources/Services/QRCode/QRCodeLoginServiceProtocol.swift b/ElementX/Sources/Services/QRCode/QRCodeLoginServiceProtocol.swift index bc0dca2254..a229092a3c 100644 --- a/ElementX/Sources/Services/QRCode/QRCodeLoginServiceProtocol.swift +++ b/ElementX/Sources/Services/QRCode/QRCodeLoginServiceProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Services/Room/InvitedRoomProxy.swift b/ElementX/Sources/Services/Room/InvitedRoomProxy.swift new file mode 100644 index 0000000000..291bfa3304 --- /dev/null +++ b/ElementX/Sources/Services/Room/InvitedRoomProxy.swift @@ -0,0 +1,102 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Foundation +import MatrixRustSDK +import UIKit + +class InvitedRoomProxy: InvitedRoomProxyProtocol { + private let roomListItem: RoomListItemProtocol + private let room: RoomProtocol + + // A room identifier is constant and lazy stops it from being fetched + // multiple times over FFI + lazy var id: String = room.id() + + var canonicalAlias: String? { + room.canonicalAlias() + } + + var ownUserID: String { + room.ownUserId() + } + + var name: String? { + roomListItem.displayName() + } + + var topic: String? { + room.topic() + } + + var avatarURL: URL? { + roomListItem.avatarUrl().flatMap(URL.init(string:)) + } + + var avatar: RoomAvatar { + if isDirect, avatarURL == nil { + let heroes = room.heroes() + + if heroes.count == 1 { + return .heroes(heroes.map(UserProfileProxy.init)) + } + } + + return .room(id: id, name: name, avatarURL: avatarURL) + } + + var isDirect: Bool { + room.isDirect() + } + + var isPublic: Bool { + room.isPublic() + } + + var isSpace: Bool { + room.isSpace() + } + + var joinedMembersCount: Int { + Int(room.joinedMembersCount()) + } + + var activeMembersCount: Int { + Int(room.activeMembersCount()) + } + + var inviter: RoomMemberProxyProtocol? { + get async { + await (try? roomListItem.roomInfo().inviter).map(RoomMemberProxy.init) + } + } + + init(roomListItem: RoomListItemProtocol, + room: RoomProtocol) { + self.roomListItem = roomListItem + self.room = room + } + + func acceptInvitation() async -> Result { + do { + try await room.join() + return .success(()) + } catch { + MXLog.error("Failed accepting invitation with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func rejectInvitation() async -> Result { + do { + return try await .success(room.leave()) + } catch { + MXLog.error("Failed rejecting invitiation with error: \(error)") + return .failure(.sdkError(error)) + } + } +} diff --git a/ElementX/Sources/Services/Room/JoinedRoomProxy.swift b/ElementX/Sources/Services/Room/JoinedRoomProxy.swift new file mode 100644 index 0000000000..e23cd573a1 --- /dev/null +++ b/ElementX/Sources/Services/Room/JoinedRoomProxy.swift @@ -0,0 +1,737 @@ +// +// 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 Foundation +import MatrixRustSDK +import UIKit + +class JoinedRoomProxy: JoinedRoomProxyProtocol { + private let roomListService: RoomListServiceProtocol + private let roomListItem: RoomListItemProtocol + private let room: RoomProtocol + let timeline: TimelineProxyProtocol + + private var innerPinnedEventsTimeline: TimelineProxyProtocol? + private var innerPinnedEventsTimelineTask: Task? + var pinnedEventsTimeline: TimelineProxyProtocol? { + get async { + // Check if is already available. + if let innerPinnedEventsTimeline { + return innerPinnedEventsTimeline + // Otherwise check if there is already a task loading it, and wait for it. + } else if let innerPinnedEventsTimelineTask, + let value = await innerPinnedEventsTimelineTask.value { + return value + // Else create and store a new task to load it and wait for it. + } else { + let task = Task { [weak self] in + guard let self else { + return nil + } + + do { + let timeline = try await TimelineProxy(timeline: room.pinnedEventsTimeline(internalIdPrefix: nil, + maxEventsToLoad: 100, + maxConcurrentRequests: 10), + kind: .pinned) + await timeline.subscribeForUpdates() + innerPinnedEventsTimeline = timeline + return timeline + } catch { + MXLog.error("Failed creating pinned events timeline with error: \(error)") + return nil + } + } + + innerPinnedEventsTimelineTask = task + return await task.value + } + } + } + + // periphery:ignore - required for instance retention in the rust codebase + private var roomInfoObservationToken: TaskHandle? + // periphery:ignore - required for instance retention in the rust codebase + private var typingNotificationObservationToken: TaskHandle? + + private var subscribedForUpdates = false + + private let membersSubject = CurrentValueSubject<[RoomMemberProxyProtocol], Never>([]) + var membersPublisher: CurrentValuePublisher<[RoomMemberProxyProtocol], Never> { + membersSubject.asCurrentValuePublisher() + } + + private let typingMembersSubject = CurrentValueSubject<[String], Never>([]) + var typingMembersPublisher: CurrentValuePublisher<[String], Never> { + typingMembersSubject.asCurrentValuePublisher() + } + + private let actionsSubject = PassthroughSubject() + var actionsPublisher: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + // A room identifier is constant and lazy stops it from being fetched + // multiple times over FFI + lazy var id: String = room.id() + + var canonicalAlias: String? { + room.canonicalAlias() + } + + var ownUserID: String { + room.ownUserId() + } + + var name: String? { + roomListItem.displayName() + } + + var topic: String? { + room.topic() + } + + var avatarURL: URL? { + roomListItem.avatarUrl().flatMap(URL.init(string:)) + } + + var avatar: RoomAvatar { + if isDirect, avatarURL == nil { + let heroes = room.heroes() + + if heroes.count == 1 { + return .heroes(heroes.map(UserProfileProxy.init)) + } + } + + return .room(id: id, name: name, avatarURL: avatarURL) + } + + var isDirect: Bool { + room.isDirect() + } + + var isPublic: Bool { + room.isPublic() + } + + var isSpace: Bool { + room.isSpace() + } + + var joinedMembersCount: Int { + Int(room.joinedMembersCount()) + } + + var activeMembersCount: Int { + Int(room.activeMembersCount()) + } + + var isEncrypted: Bool { + (try? room.isEncrypted()) ?? false + } + + var isFavourite: Bool { + get async { + await (try? room.roomInfo().isFavourite) ?? false + } + } + + var pinnedEventIDs: Set { + get async { + guard let pinnedEventIDs = try? await room.roomInfo().pinnedEventIds else { + return [] + } + return .init(pinnedEventIDs) + } + } + + var hasOngoingCall: Bool { + room.hasActiveRoomCall() + } + + var activeRoomCallParticipants: [String] { + room.activeRoomCallParticipants() + } + + init(roomListService: RoomListServiceProtocol, + roomListItem: RoomListItemProtocol, + room: RoomProtocol) async throws { + self.roomListService = roomListService + self.roomListItem = roomListItem + self.room = room + + timeline = try await TimelineProxy(timeline: room.timeline(), kind: .live) + + Task { + await updateMembers() + } + } + + func subscribeForUpdates() async { + guard !subscribedForUpdates else { + MXLog.warning("Room already subscribed for updates") + return + } + + subscribedForUpdates = true + let settings = RoomSubscription(requiredState: SlidingSyncConstants.defaultRequiredState, + timelineLimit: SlidingSyncConstants.defaultTimelineLimit, + includeHeroes: false) // We don't need heroes here as they're already included in the `all_rooms` list + do { + try roomListService.subscribeToRooms(roomIds: [id], settings: settings) + } catch { + MXLog.error("Failed subscribing to room with error: \(error)") + } + + await timeline.subscribeForUpdates() + + subscribeToRoomInfoUpdates() + + subscribeToTypingNotifications() + } + + func subscribeToRoomInfoUpdates() { + guard roomInfoObservationToken == nil else { + return + } + + roomInfoObservationToken = room.subscribeToRoomInfoUpdates(listener: RoomInfoUpdateListener { [weak self] in + MXLog.info("Received room info update") + self?.actionsSubject.send(.roomInfoUpdate) + }) + } + + func timelineFocusedOnEvent(eventID: String, numberOfEvents: UInt16) async -> Result { + do { + let timeline = try await room.timelineFocusedOnEvent(eventId: eventID, numContextEvents: numberOfEvents, internalIdPrefix: UUID().uuidString) + return .success(TimelineProxy(timeline: timeline, kind: .detached)) + } catch let error as FocusEventError { + switch error { + case .InvalidEventId(_, let error): + MXLog.error("Invalid event \(eventID) Error: \(error)") + return .failure(.eventNotFound) + case .EventNotFound: + MXLog.error("Event \(eventID) not found.") + return .failure(.eventNotFound) + case .Other(let message): + MXLog.error("Failed to create a timeline focussed on event \(eventID) Error: \(message)") + return .failure(.sdkError(error)) + } + } catch { + MXLog.error("Unexpected error: \(error)") + return .failure(.sdkError(error)) + } + } + + func redact(_ eventID: String) async -> Result { + do { + try await room.redact(eventId: eventID, reason: nil) + return .success(()) + } catch { + MXLog.error("Failed redacting eventID: \(eventID) with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func reportContent(_ eventID: String, reason: String?) async -> Result { + do { + try await room.reportContent(eventId: eventID, score: nil, reason: reason) + return .success(()) + } catch { + MXLog.error("Failed reporting eventID: \(eventID) with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func updateMembers() async { + // We always update members first using the no sync API in case internet is not readily available + // To get the members stored on disk first, this API call is very fast. + do { + let membersNoSyncIterator = try await room.membersNoSync() + if let members = membersNoSyncIterator.nextChunk(chunkSize: membersNoSyncIterator.len()) { + membersSubject.value = members.map(RoomMemberProxy.init) + } + } catch { + MXLog.error("[RoomProxy] Failed updating members using no sync API: \(error)") + } + + do { + // Then we update members using the sync API, this is slower but will get us the latest members + let membersIterator = try await room.members() + if let members = membersIterator.nextChunk(chunkSize: membersIterator.len()) { + membersSubject.value = members.map(RoomMemberProxy.init) + } + } catch { + MXLog.error("[RoomProxy] Failed updating members using sync API: \(error)") + } + } + + func getMember(userID: String) async -> Result { + if let member = membersPublisher.value.filter({ $0.userID == userID }).first { + return .success(member) + } + + do { + let member = try await room.member(userId: userID) + return .success(RoomMemberProxy(member: member)) + } catch { + MXLog.error("Failed retrieving member \(userID) with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func leaveRoom() async -> Result { + do { + try await room.leave() + return .success(()) + } catch { + MXLog.error("Failed leaving room with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func invite(userID: String) async -> Result { + do { + MXLog.info("Inviting user \(userID)") + return try await .success(room.inviteUserById(userId: userID)) + } catch { + MXLog.error("Failed inviting user \(userID) with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func setName(_ name: String) async -> Result { + do { + return try await .success(room.setName(name: name)) + } catch { + MXLog.error("Failed setting name with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func setTopic(_ topic: String) async -> Result { + do { + return try await .success(room.setTopic(topic: topic)) + } catch { + MXLog.error("Failed setting topic with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func removeAvatar() async -> Result { + do { + return try await .success(room.removeAvatar()) + } catch { + MXLog.error("Failed removing avatar with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func uploadAvatar(media: MediaInfo) async -> Result { + guard case let .image(imageURL, _, _) = media, let mimeType = media.mimeType else { + MXLog.error("Failed uploading avatar, invalid media: \(media)") + return .failure(.invalidMedia) + } + + do { + let data = try Data(contentsOf: imageURL) + return try await .success(room.uploadAvatar(mimeType: mimeType, data: data, mediaInfo: nil)) + } catch { + MXLog.error("Failed uploading avatar with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func markAsRead(receiptType: ReceiptType) async -> Result { + do { + try await room.markAsRead(receiptType: receiptType) + return .success(()) + } catch { + MXLog.error("Failed marking room \(id) as read with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func edit(eventID: String, newContent: RoomMessageEventContentWithoutRelation) async -> Result { + do { + try await room.edit(eventId: eventID, newContent: newContent) + return .success(()) + } catch { + MXLog.error("Failed editing event id \(eventID), in room \(id) with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func sendTypingNotification(isTyping: Bool) async -> Result { + MXLog.info("Sending typing notification isTyping: \(isTyping)") + + do { + try await room.typingNotice(isTyping: isTyping) + return .success(()) + } catch { + MXLog.error("Failed sending typing notice with error: \(error)") + return .failure(.sdkError(error)) + } + } + + 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) + } + + do { + try await room.tryResend(transactionId: transactionID) + return .success(()) + } catch { + MXLog.error("Failed resending \(transactionID) 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) + } + + do { + try await room.withdrawVerificationAndResend(userIds: userIDs, transactionId: transactionID) + return .success(()) + } catch { + MXLog.error("Failed withdrawing verification of \(userIDs) and resending \(transactionID) with error: \(error)") + return .failure(.sdkError(error)) + } + } + + // MARK: - Room flags + + func flagAsUnread(_ isUnread: Bool) async -> Result { + MXLog.info("Flagging room \(id) as unread: \(isUnread)") + + do { + try await room.setUnreadFlag(newValue: isUnread) + return .success(()) + } catch { + MXLog.error("Failed marking room \(id) as unread: \(isUnread) with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func flagAsFavourite(_ isFavourite: Bool) async -> Result { + do { + try await room.setIsFavourite(isFavourite: isFavourite, tagOrder: nil) + return .success(()) + } catch { + MXLog.error("Failed flagging room \(id) as favourite with error: \(error)") + return .failure(.sdkError(error)) + } + } + + // MARK: - Power Levels + + func powerLevels() async -> Result { + do { + return try await .success(room.getPowerLevels()) + } catch { + MXLog.error("Failed building the current power level settings: \(error)") + return .failure(.sdkError(error)) + } + } + + func applyPowerLevelChanges(_ changes: RoomPowerLevelChanges) async -> Result { + do { + return try await .success(room.applyPowerLevelChanges(changes: changes)) + } catch { + MXLog.error("Failed applying the power level changes: \(error)") + return .failure(.sdkError(error)) + } + } + + func resetPowerLevels() async -> Result { + do { + return try await .success(room.resetPowerLevels()) + } catch { + MXLog.error("Failed resetting the power levels: \(error)") + return .failure(.sdkError(error)) + } + } + + func suggestedRole(for userID: String) async -> Result { + do { + return try await .success(room.suggestedRoleForUser(userId: userID)) + } catch { + MXLog.error("Failed getting a user's role: \(error)") + return .failure(.sdkError(error)) + } + } + + func updatePowerLevelsForUsers(_ updates: [(userID: String, powerLevel: Int64)]) async -> Result { + do { + let updates = updates.map { UserPowerLevelUpdate(userId: $0.userID, powerLevel: $0.powerLevel) } + return try await .success(room.updatePowerLevelsForUsers(updates: updates)) + } catch { + MXLog.error("Failed updating user power levels changes: \(error)") + return .failure(.sdkError(error)) + } + } + + func canUser(userID: String, sendStateEvent event: StateEventType) async -> Result { + do { + return try await .success(room.canUserSendState(userId: userID, stateEvent: event)) + } catch { + MXLog.error("Failed checking if the user can send \(event) with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func canUserInvite(userID: String) async -> Result { + do { + return try await .success(room.canUserInvite(userId: userID)) + } catch { + MXLog.error("Failed checking if the user can invite with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func canUserRedactOther(userID: String) async -> Result { + do { + return try await .success(room.canUserRedactOther(userId: userID)) + } catch { + MXLog.error("Failed checking if the user can redact others with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func canUserRedactOwn(userID: String) async -> Result { + do { + return try await .success(room.canUserRedactOwn(userId: userID)) + } catch { + MXLog.error("Failed checking if the user can redact self with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func canUserKick(userID: String) async -> Result { + do { + return try await .success(room.canUserKick(userId: userID)) + } catch { + MXLog.error("Failed checking if the user can kick with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func canUserBan(userID: String) async -> Result { + do { + return try await .success(room.canUserBan(userId: userID)) + } catch { + MXLog.error("Failed checking if the user can ban with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func canUserTriggerRoomNotification(userID: String) async -> Result { + do { + return try await .success(room.canUserTriggerRoomNotification(userId: userID)) + } catch { + MXLog.error("Failed checking if the user can trigger room notification with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func canUserPinOrUnpin(userID: String) async -> Result { + do { + return try await .success(room.canUserPinUnpin(userId: userID)) + } catch { + MXLog.error("Failed checking if the user can pin or unnpin: \(error)") + return .failure(.sdkError(error)) + } + } + + // MARK: - Moderation + + func kickUser(_ userID: String) async -> Result { + do { + try await room.kickUser(userId: userID, reason: nil) + return .success(()) + } catch { + MXLog.error("Failed kicking \(userID) with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func banUser(_ userID: String) async -> Result { + do { + try await room.banUser(userId: userID, reason: nil) + return .success(()) + } catch { + MXLog.error("Failed banning \(userID) with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func unbanUser(_ userID: String) async -> Result { + do { + try await room.unbanUser(userId: userID, reason: nil) + return .success(()) + } catch { + MXLog.error("Failed unbanning \(userID) with error: \(error)") + return .failure(.sdkError(error)) + } + } + + // MARK: - Element Call + + func canUserJoinCall(userID: String) async -> Result { + do { + return try await .success(room.canUserSendState(userId: userID, stateEvent: .callMember)) + } catch { + MXLog.error("Failed checking if the user can trigger room notification with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func elementCallWidgetDriver(deviceID: String) -> ElementCallWidgetDriverProtocol { + ElementCallWidgetDriver(room: room, deviceID: deviceID) + } + + func sendCallNotificationIfNeeded() async -> Result { + do { + try await room.sendCallNotificationIfNeeded() + return .success(()) + } catch { + MXLog.error("Failed room call notification with error: \(error)") + return .failure(.sdkError(error)) + } + } + + // MARK: - Permalinks + + func matrixToPermalink() async -> Result { + do { + let urlString = try await room.matrixToPermalink() + + guard let url = URL(string: urlString) else { + MXLog.error("Failed creating permalink for roomID: \(id), invalid permalink URL string: \(urlString)") + return .failure(.invalidURL) + } + + return .success(url) + } catch { + MXLog.error("Failed creating permalink for roomID: \(id) with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func matrixToEventPermalink(_ eventID: String) async -> Result { + do { + let urlString = try await room.matrixToEventPermalink(eventId: eventID) + + guard let url = URL(string: urlString) else { + MXLog.error("Failed creating permalink for eventID: \(eventID), invalid permalink URL string: \(urlString)") + return .failure(.invalidURL) + } + + return .success(url) + } catch { + MXLog.error("Failed creating permalink for eventID: \(eventID) with error: \(error)") + return .failure(.sdkError(error)) + } + } + + // MARK: - Drafts + + func saveDraft(_ draft: ComposerDraft) async -> Result { + do { + try await room.saveComposerDraft(draft: draft) + return .success(()) + } catch { + MXLog.error("Failed saving draft with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func loadDraft() async -> Result { + do { + return try await .success(room.loadComposerDraft()) + } catch { + MXLog.error("Failed restoring draft with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func clearDraft() async -> Result { + do { + try await room.clearComposerDraft() + return .success(()) + } catch { + MXLog.error("Failed clearing draft with error: \(error)") + return .failure(.sdkError(error)) + } + } + + // MARK: - Private + + private func subscribeToTypingNotifications() { + typingNotificationObservationToken = room.subscribeToTypingNotifications(listener: RoomTypingNotificationUpdateListener { [weak self] typingUserIDs in + guard let self else { return } + + MXLog.info("Received typing notification update, typingUsers: \(typingUserIDs)") + + let typingMembers = typingUserIDs.compactMap { userID in + if let member = self.membersPublisher.value.filter({ $0.userID == userID }).first { + return member.displayName ?? member.userID + } else { + return userID + } + } + + typingMembersSubject.send(typingMembers) + }) + } +} + +private final class RoomInfoUpdateListener: RoomInfoListener { + private let onUpdateClosure: () -> Void + + init(_ onUpdateClosure: @escaping () -> Void) { + self.onUpdateClosure = onUpdateClosure + } + + func call(roomInfo: RoomInfo) { + onUpdateClosure() + } +} + +private final class RoomTypingNotificationUpdateListener: TypingNotificationsListener { + private let onUpdateClosure: ([String]) -> Void + + init(_ onUpdateClosure: @escaping ([String]) -> Void) { + self.onUpdateClosure = onUpdateClosure + } + + func call(typingUserIds: [String]) { + onUpdateClosure(typingUserIds) + } +} diff --git a/ElementX/Sources/Services/Room/RoomDetails.swift b/ElementX/Sources/Services/Room/RoomDetails.swift index 66b1f19a32..67c6ccb38a 100644 --- a/ElementX/Sources/Services/Room/RoomDetails.swift +++ b/ElementX/Sources/Services/Room/RoomDetails.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Room/RoomMember/RoomMemberDetails.swift b/ElementX/Sources/Services/Room/RoomMember/RoomMemberDetails.swift index 671602f7b1..e75285fc90 100644 --- a/ElementX/Sources/Services/Room/RoomMember/RoomMemberDetails.swift +++ b/ElementX/Sources/Services/Room/RoomMember/RoomMemberDetails.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Room/RoomMember/RoomMemberProxy.swift b/ElementX/Sources/Services/Room/RoomMember/RoomMemberProxy.swift index 643fd4c8b5..856ec67ae2 100644 --- a/ElementX/Sources/Services/Room/RoomMember/RoomMemberProxy.swift +++ b/ElementX/Sources/Services/Room/RoomMember/RoomMemberProxy.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Room/RoomMember/RoomMemberProxyProtocol.swift b/ElementX/Sources/Services/Room/RoomMember/RoomMemberProxyProtocol.swift index 0802129d45..6c1fe0afe2 100644 --- a/ElementX/Sources/Services/Room/RoomMember/RoomMemberProxyProtocol.swift +++ b/ElementX/Sources/Services/Room/RoomMember/RoomMemberProxyProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Room/RoomPermissions.swift b/ElementX/Sources/Services/Room/RoomPermissions.swift index d466a14b79..2c3b32db6e 100644 --- a/ElementX/Sources/Services/Room/RoomPermissions.swift +++ b/ElementX/Sources/Services/Room/RoomPermissions.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Room/RoomProxy.swift b/ElementX/Sources/Services/Room/RoomProxy.swift deleted file mode 100644 index 16eb1bb891..0000000000 --- a/ElementX/Sources/Services/Room/RoomProxy.swift +++ /dev/null @@ -1,730 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Combine -import Foundation -import MatrixRustSDK -import UIKit - -class RoomProxy: RoomProxyProtocol { - private let roomListService: RoomListServiceProtocol - private let roomListItem: RoomListItemProtocol - private let room: RoomProtocol - let timeline: TimelineProxyProtocol - - private var innerPinnedEventsTimeline: TimelineProxyProtocol? - private var innerPinnedEventsTimelineTask: Task? - var pinnedEventsTimeline: TimelineProxyProtocol? { - get async { - // Check if is alrrady available. - if let innerPinnedEventsTimeline { - return innerPinnedEventsTimeline - // Otherwise check if there is already a task loading it, and wait for it. - } else if let innerPinnedEventsTimelineTask, - let value = await innerPinnedEventsTimelineTask.value { - return value - // Else create and store a new task to load it and wait for it. - } else { - let task = Task { [weak self] in - guard let self else { - return nil - } - - do { - let timeline = try await TimelineProxy(timeline: room.pinnedEventsTimeline(internalIdPrefix: nil, maxEventsToLoad: 100), isLive: false) - await timeline.subscribeForUpdates() - innerPinnedEventsTimeline = timeline - return timeline - } catch { - MXLog.error("Failed creating pinned events timeline with error: \(error)") - return nil - } - } - - innerPinnedEventsTimelineTask = task - return await task.value - } - } - } - - // periphery:ignore - required for instance retention in the rust codebase - private var roomInfoObservationToken: TaskHandle? - // periphery:ignore - required for instance retention in the rust codebase - private var typingNotificationObservationToken: TaskHandle? - - private var subscribedForUpdates = false - - private let membersSubject = CurrentValueSubject<[RoomMemberProxyProtocol], Never>([]) - var membersPublisher: CurrentValuePublisher<[RoomMemberProxyProtocol], Never> { - membersSubject.asCurrentValuePublisher() - } - - private let typingMembersSubject = CurrentValueSubject<[String], Never>([]) - var typingMembersPublisher: CurrentValuePublisher<[String], Never> { - typingMembersSubject.asCurrentValuePublisher() - } - - private let actionsSubject = PassthroughSubject() - var actionsPublisher: AnyPublisher { - actionsSubject.eraseToAnyPublisher() - } - - lazy var id: String = room.id() - - var ownUserID: String { - room.ownUserId() - } - - var name: String? { - roomListItem.displayName() - } - - var topic: String? { - room.topic() - } - - var membership: Membership { - room.membership() - } - - var inviter: RoomMemberProxyProtocol? { - get async { - await (try? roomListItem.roomInfo().inviter).map(RoomMemberProxy.init) - } - } - - var isDirect: Bool { - room.isDirect() - } - - var isPublic: Bool { - room.isPublic() - } - - var isSpace: Bool { - room.isSpace() - } - - var isEncrypted: Bool { - (try? room.isEncrypted()) ?? false - } - - var isFavourite: Bool { - get async { - await (try? room.roomInfo().isFavourite) ?? false - } - } - - var pinnedEventIDs: Set { - get async { - guard let pinnedEventIDs = try? await room.roomInfo().pinnedEventIds else { - return [] - } - return .init(pinnedEventIDs) - } - } - - var hasOngoingCall: Bool { - room.hasActiveRoomCall() - } - - var activeRoomCallParticipants: [String] { - room.activeRoomCallParticipants() - } - - var canonicalAlias: String? { - room.canonicalAlias() - } - - var avatarURL: URL? { - roomListItem.avatarUrl().flatMap(URL.init(string:)) - } - - var avatar: RoomAvatar { - if isDirect, avatarURL == nil { - let heroes = room.heroes() - - if heroes.count == 1 { - return .heroes(heroes.map(UserProfileProxy.init)) - } - } - - return .room(id: id, name: name, avatarURL: avatarURL) - } - - var joinedMembersCount: Int { - Int(room.joinedMembersCount()) - } - - var activeMembersCount: Int { - Int(room.activeMembersCount()) - } - - init?(roomListService: RoomListServiceProtocol, - roomListItem: RoomListItemProtocol, - room: RoomProtocol) async { - self.roomListService = roomListService - self.roomListItem = roomListItem - self.room = room - - do { - timeline = try await TimelineProxy(timeline: room.timeline(), isLive: true) - } catch { - MXLog.error("Failed creating timeline with error: \(error)") - return nil - } - - Task { - await updateMembers() - } - } - - func subscribeForUpdates() async { - guard !subscribedForUpdates else { - MXLog.warning("Room already subscribed for updates") - return - } - - subscribedForUpdates = true - let settings = RoomSubscription(requiredState: SlidingSyncConstants.defaultRequiredState, - timelineLimit: SlidingSyncConstants.defaultTimelineLimit, - includeHeroes: false) // We don't need heroes here as they're already included in the `all_rooms` list - do { - try roomListService.subscribeToRooms(roomIds: [id], settings: settings) - } catch { - MXLog.error("Failed subscribing to room with error: \(error)") - } - - await timeline.subscribeForUpdates() - - subscribeToRoomInfoUpdates() - - subscribeToTypingNotifications() - } - - func subscribeToRoomInfoUpdates() { - guard roomInfoObservationToken == nil else { - return - } - - roomInfoObservationToken = room.subscribeToRoomInfoUpdates(listener: RoomInfoUpdateListener { [weak self] in - MXLog.info("Received room info update") - self?.actionsSubject.send(.roomInfoUpdate) - }) - } - - func timelineFocusedOnEvent(eventID: String, numberOfEvents: UInt16) async -> Result { - do { - let timeline = try await room.timelineFocusedOnEvent(eventId: eventID, numContextEvents: numberOfEvents, internalIdPrefix: UUID().uuidString) - return .success(TimelineProxy(timeline: timeline, isLive: false)) - } catch let error as FocusEventError { - switch error { - case .InvalidEventId(_, let error): - MXLog.error("Invalid event \(eventID) Error: \(error)") - return .failure(.eventNotFound) - case .EventNotFound: - MXLog.error("Event \(eventID) not found.") - return .failure(.eventNotFound) - case .Other(let message): - MXLog.error("Failed to create a timeline focussed on event \(eventID) Error: \(message)") - return .failure(.sdkError(error)) - } - } catch { - MXLog.error("Unexpected error: \(error)") - return .failure(.sdkError(error)) - } - } - - func redact(_ eventID: String) async -> Result { - do { - try await room.redact(eventId: eventID, reason: nil) - return .success(()) - } catch { - MXLog.error("Failed redacting eventID: \(eventID) with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func reportContent(_ eventID: String, reason: String?) async -> Result { - do { - try await room.reportContent(eventId: eventID, score: nil, reason: reason) - return .success(()) - } catch { - MXLog.error("Failed reporting eventID: \(eventID) with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func updateMembers() async { - // We always update members first using the no sync API in case internet is not readily available - // To get the members stored on disk first, this API call is very fast. - do { - let membersNoSyncIterator = try await room.membersNoSync() - if let members = membersNoSyncIterator.nextChunk(chunkSize: membersNoSyncIterator.len()) { - membersSubject.value = members.map(RoomMemberProxy.init) - } - } catch { - MXLog.error("[RoomProxy] Failed updating members using no sync API: \(error)") - } - - do { - // Then we update members using the sync API, this is slower but will get us the latest members - let membersIterator = try await room.members() - if let members = membersIterator.nextChunk(chunkSize: membersIterator.len()) { - membersSubject.value = members.map(RoomMemberProxy.init) - } - } catch { - MXLog.error("[RoomProxy] Failed updating members using sync API: \(error)") - } - } - - func getMember(userID: String) async -> Result { - if let member = membersPublisher.value.filter({ $0.userID == userID }).first { - return .success(member) - } - - do { - let member = try await room.member(userId: userID) - return .success(RoomMemberProxy(member: member)) - } catch { - MXLog.error("Failed retrieving member \(userID) with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func leaveRoom() async -> Result { - do { - try await room.leave() - return .success(()) - } catch { - MXLog.error("Failed leaving room with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func rejectInvitation() async -> Result { - do { - return try await .success(room.leave()) - } catch { - MXLog.error("Failed rejecting invitiation with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func acceptInvitation() async -> Result { - do { - try await room.join() - return .success(()) - } catch { - MXLog.error("Failed accepting invitation with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func invite(userID: String) async -> Result { - do { - MXLog.info("Inviting user \(userID)") - return try await .success(room.inviteUserById(userId: userID)) - } catch { - MXLog.error("Failed inviting user \(userID) with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func setName(_ name: String) async -> Result { - do { - return try await .success(room.setName(name: name)) - } catch { - MXLog.error("Failed setting name with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func setTopic(_ topic: String) async -> Result { - do { - return try await .success(room.setTopic(topic: topic)) - } catch { - MXLog.error("Failed setting topic with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func removeAvatar() async -> Result { - do { - return try await .success(room.removeAvatar()) - } catch { - MXLog.error("Failed removing avatar with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func uploadAvatar(media: MediaInfo) async -> Result { - guard case let .image(imageURL, _, _) = media, let mimeType = media.mimeType else { - MXLog.error("Failed uploading avatar, invalid media: \(media)") - return .failure(.invalidMedia) - } - - do { - let data = try Data(contentsOf: imageURL) - return try await .success(room.uploadAvatar(mimeType: mimeType, data: data, mediaInfo: nil)) - } catch { - MXLog.error("Failed uploading avatar with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func markAsRead(receiptType: ReceiptType) async -> Result { - do { - try await room.markAsRead(receiptType: receiptType) - return .success(()) - } catch { - MXLog.error("Failed marking room \(id) as read with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func edit(eventID: String, newContent: RoomMessageEventContentWithoutRelation) async -> Result { - do { - try await room.edit(eventId: eventID, newContent: newContent) - return .success(()) - } catch { - MXLog.error("Failed editing event id \(eventID), in room \(id) with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func sendTypingNotification(isTyping: Bool) async -> Result { - MXLog.info("Sending typing notification isTyping: \(isTyping)") - - do { - try await room.typingNotice(isTyping: isTyping) - return .success(()) - } catch { - MXLog.error("Failed sending typing notice with error: \(error)") - return .failure(.sdkError(error)) - } - } - - // MARK: - Room flags - - func flagAsUnread(_ isUnread: Bool) async -> Result { - MXLog.info("Flagging room \(id) as unread: \(isUnread)") - - do { - try await room.setUnreadFlag(newValue: isUnread) - return .success(()) - } catch { - MXLog.error("Failed marking room \(id) as unread: \(isUnread) with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func flagAsFavourite(_ isFavourite: Bool) async -> Result { - do { - try await room.setIsFavourite(isFavourite: isFavourite, tagOrder: nil) - return .success(()) - } catch { - MXLog.error("Failed flagging room \(id) as favourite with error: \(error)") - return .failure(.sdkError(error)) - } - } - - // MARK: - Power Levels - - func powerLevels() async -> Result { - do { - return try await .success(room.getPowerLevels()) - } catch { - MXLog.error("Failed building the current power level settings: \(error)") - return .failure(.sdkError(error)) - } - } - - func applyPowerLevelChanges(_ changes: RoomPowerLevelChanges) async -> Result { - do { - return try await .success(room.applyPowerLevelChanges(changes: changes)) - } catch { - MXLog.error("Failed applying the power level changes: \(error)") - return .failure(.sdkError(error)) - } - } - - func resetPowerLevels() async -> Result { - do { - return try await .success(room.resetPowerLevels()) - } catch { - MXLog.error("Failed resetting the power levels: \(error)") - return .failure(.sdkError(error)) - } - } - - func suggestedRole(for userID: String) async -> Result { - do { - return try await .success(room.suggestedRoleForUser(userId: userID)) - } catch { - MXLog.error("Failed getting a user's role: \(error)") - return .failure(.sdkError(error)) - } - } - - func updatePowerLevelsForUsers(_ updates: [(userID: String, powerLevel: Int64)]) async -> Result { - do { - let updates = updates.map { UserPowerLevelUpdate(userId: $0.userID, powerLevel: $0.powerLevel) } - return try await .success(room.updatePowerLevelsForUsers(updates: updates)) - } catch { - MXLog.error("Failed updating user power levels changes: \(error)") - return .failure(.sdkError(error)) - } - } - - func canUser(userID: String, sendStateEvent event: StateEventType) async -> Result { - do { - return try await .success(room.canUserSendState(userId: userID, stateEvent: event)) - } catch { - MXLog.error("Failed checking if the user can send \(event) with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func canUserInvite(userID: String) async -> Result { - do { - return try await .success(room.canUserInvite(userId: userID)) - } catch { - MXLog.error("Failed checking if the user can invite with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func canUserRedactOther(userID: String) async -> Result { - do { - return try await .success(room.canUserRedactOther(userId: userID)) - } catch { - MXLog.error("Failed checking if the user can redact others with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func canUserRedactOwn(userID: String) async -> Result { - do { - return try await .success(room.canUserRedactOwn(userId: userID)) - } catch { - MXLog.error("Failed checking if the user can redact self with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func canUserKick(userID: String) async -> Result { - do { - return try await .success(room.canUserKick(userId: userID)) - } catch { - MXLog.error("Failed checking if the user can kick with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func canUserBan(userID: String) async -> Result { - do { - return try await .success(room.canUserBan(userId: userID)) - } catch { - MXLog.error("Failed checking if the user can ban with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func canUserTriggerRoomNotification(userID: String) async -> Result { - do { - return try await .success(room.canUserTriggerRoomNotification(userId: userID)) - } catch { - MXLog.error("Failed checking if the user can trigger room notification with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func canUserPinOrUnpin(userID: String) async -> Result { - do { - return try await .success(room.canUserPinUnpin(userId: userID)) - } catch { - MXLog.error("Failed checking if the user can pin or unnpin: \(error)") - return .failure(.sdkError(error)) - } - } - - // MARK: - Moderation - - func kickUser(_ userID: String) async -> Result { - do { - try await room.kickUser(userId: userID, reason: nil) - return .success(()) - } catch { - MXLog.error("Failed kicking \(userID) with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func banUser(_ userID: String) async -> Result { - do { - try await room.banUser(userId: userID, reason: nil) - return .success(()) - } catch { - MXLog.error("Failed banning \(userID) with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func unbanUser(_ userID: String) async -> Result { - do { - try await room.unbanUser(userId: userID, reason: nil) - return .success(()) - } catch { - MXLog.error("Failed unbanning \(userID) with error: \(error)") - return .failure(.sdkError(error)) - } - } - - // MARK: - Element Call - - func canUserJoinCall(userID: String) async -> Result { - do { - return try await .success(room.canUserSendState(userId: userID, stateEvent: .callMember)) - } catch { - MXLog.error("Failed checking if the user can trigger room notification with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func elementCallWidgetDriver(deviceID: String) -> ElementCallWidgetDriverProtocol { - ElementCallWidgetDriver(room: room, deviceID: deviceID) - } - - func sendCallNotificationIfNeeeded() async -> Result { - do { - try await room.sendCallNotificationIfNeeded() - return .success(()) - } catch { - MXLog.error("Failed room call notification with error: \(error)") - return .failure(.sdkError(error)) - } - } - - // MARK: - Permalinks - - func matrixToPermalink() async -> Result { - do { - let urlString = try await room.matrixToPermalink() - - guard let url = URL(string: urlString) else { - MXLog.error("Failed creating permalink for roomID: \(id), invalid permalink URL string: \(urlString)") - return .failure(.invalidURL) - } - - return .success(url) - } catch { - MXLog.error("Failed creating permalink for roomID: \(id) with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func matrixToEventPermalink(_ eventID: String) async -> Result { - do { - let urlString = try await room.matrixToEventPermalink(eventId: eventID) - - guard let url = URL(string: urlString) else { - MXLog.error("Failed creating permalink for eventID: \(eventID), invalid permalink URL string: \(urlString)") - return .failure(.invalidURL) - } - - return .success(url) - } catch { - MXLog.error("Failed creating permalink for eventID: \(eventID) with error: \(error)") - return .failure(.sdkError(error)) - } - } - - // MARK: - Drafts - - func saveDraft(_ draft: ComposerDraft) async -> Result { - do { - try await room.saveComposerDraft(draft: draft) - return .success(()) - } catch { - MXLog.error("Failed saving draft with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func loadDraft() async -> Result { - do { - return try await .success(room.loadComposerDraft()) - } catch { - MXLog.error("Failed restoring draft with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func clearDraft() async -> Result { - do { - try await room.clearComposerDraft() - return .success(()) - } catch { - MXLog.error("Failed clearing draft with error: \(error)") - return .failure(.sdkError(error)) - } - } - - // MARK: - Private - - private func subscribeToTypingNotifications() { - typingNotificationObservationToken = room.subscribeToTypingNotifications(listener: RoomTypingNotificationUpdateListener { [weak self] typingUserIDs in - guard let self else { return } - - MXLog.info("Received typing notification update, typingUsers: \(typingUserIDs)") - - let typingMembers = typingUserIDs.compactMap { userID in - if let member = self.membersPublisher.value.filter({ $0.userID == userID }).first { - return member.displayName ?? member.userID - } else { - return userID - } - } - - typingMembersSubject.send(typingMembers) - }) - } -} - -private final class RoomInfoUpdateListener: RoomInfoListener { - private let onUpdateClosure: () -> Void - - init(_ onUpdateClosure: @escaping () -> Void) { - self.onUpdateClosure = onUpdateClosure - } - - func call(roomInfo: RoomInfo) { - onUpdateClosure() - } -} - -private final class RoomTypingNotificationUpdateListener: TypingNotificationsListener { - private let onUpdateClosure: ([String]) -> Void - - init(_ onUpdateClosure: @escaping ([String]) -> Void) { - self.onUpdateClosure = onUpdateClosure - } - - func call(typingUserIds: [String]) { - onUpdateClosure(typingUserIds) - } -} diff --git a/ElementX/Sources/Services/Room/RoomProxyProtocol.swift b/ElementX/Sources/Services/Room/RoomProxyProtocol.swift index 6f95a01d2a..d2d99406cb 100644 --- a/ElementX/Sources/Services/Room/RoomProxyProtocol.swift +++ b/ElementX/Sources/Services/Room/RoomProxyProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -24,48 +15,65 @@ enum RoomProxyError: Error { case invalidURL case invalidMedia case eventNotFound + case missingTransactionID } -enum RoomProxyAction { - case roomInfoUpdate +enum RoomProxyType { + case joined(JoinedRoomProxyProtocol) + case invited(InvitedRoomProxyProtocol) + case left } // sourcery: AutoMockable protocol RoomProxyProtocol { var id: String { get } - var isDirect: Bool { get } - var isPublic: Bool { get } - var isSpace: Bool { get } - var isEncrypted: Bool { get } - var isFavourite: Bool { get async } - var pinnedEventIDs: Set { get async } - var membership: Membership { get } - var inviter: RoomMemberProxyProtocol? { get async } - - var hasOngoingCall: Bool { get } - var activeRoomCallParticipants: [String] { get } - var canonicalAlias: String? { get } + var ownUserID: String { get } var name: String? { get } - var topic: String? { get } /// The room's avatar info for use in a ``RoomAvatarImage``. var avatar: RoomAvatar { get } /// The room's avatar URL. Use this for editing and favour ``avatar`` for display. var avatarURL: URL? { get } - - var membersPublisher: CurrentValuePublisher<[RoomMemberProxyProtocol], Never> { get } - var typingMembersPublisher: CurrentValuePublisher<[String], Never> { get } + var isPublic: Bool { get } + var isDirect: Bool { get } + var isSpace: Bool { get } var joinedMembersCount: Int { get } var activeMembersCount: Int { get } +} + +// sourcery: AutoMockable +protocol InvitedRoomProxyProtocol: RoomProxyProtocol { + var inviter: RoomMemberProxyProtocol? { get async } - var actionsPublisher: AnyPublisher { get } + func rejectInvitation() async -> Result + func acceptInvitation() async -> Result +} + +enum JoinedRoomProxyAction { + case roomInfoUpdate +} + +// sourcery: AutoMockable +protocol JoinedRoomProxyProtocol: RoomProxyProtocol { + var isEncrypted: Bool { get } + var isFavourite: Bool { get async } + var pinnedEventIDs: Set { get async } + + var hasOngoingCall: Bool { get } + var activeRoomCallParticipants: [String] { get } + + var membersPublisher: CurrentValuePublisher<[RoomMemberProxyProtocol], Never> { get } + + var typingMembersPublisher: CurrentValuePublisher<[String], Never> { get } + + var actionsPublisher: AnyPublisher { get } var timeline: TimelineProxyProtocol { get } @@ -87,10 +95,6 @@ protocol RoomProxyProtocol { func getMember(userID: String) async -> Result - func rejectInvitation() async -> Result - - func acceptInvitation() async -> Result - func invite(userID: String) async -> Result func setName(_ name: String) async -> Result @@ -108,6 +112,12 @@ protocol 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]], itemID: TimelineItemIdentifier) async -> Result + + func withdrawVerificationAndResend(userIDs: [String], itemID: TimelineItemIdentifier) async -> Result + // MARK: - Room Flags func flagAsUnread(_ isUnread: Bool) async -> Result @@ -141,7 +151,7 @@ protocol RoomProxyProtocol { func canUserJoinCall(userID: String) async -> Result func elementCallWidgetDriver(deviceID: String) -> ElementCallWidgetDriverProtocol - func sendCallNotificationIfNeeeded() async -> Result + func sendCallNotificationIfNeeded() async -> Result // MARK: - Permalinks @@ -155,7 +165,7 @@ protocol RoomProxyProtocol { func clearDraft() async -> Result } -extension RoomProxyProtocol { +extension JoinedRoomProxyProtocol { var details: RoomDetails { RoomDetails(id: id, name: name, diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomEventStringBuilder.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomEventStringBuilder.swift index fcf4fdb12f..beed3f206a 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomEventStringBuilder.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomEventStringBuilder.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomMessageEventStringBuilder.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomMessageEventStringBuilder.swift index 93c430f931..2c7a1e07e2 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomMessageEventStringBuilder.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomMessageEventStringBuilder.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomSummary.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomSummary.swift index 9de0287e41..942a78704f 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomSummary.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomSummary.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift index cc57715d9a..0d9921a707 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -30,10 +21,13 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol { private let serialDispatchQueue: DispatchQueue + private let visibleItemRangePublisher = CurrentValueSubject, Never>(0..<0) + // periphery:ignore - retaining purpose private var roomList: RoomListProtocol? private var cancellables = Set() + private var roomListServiceStateCancellable: AnyCancellable? private var listUpdatesSubscriptionResult: RoomListEntriesWithDynamicAdaptersResult? private var stateUpdatesTaskHandle: TaskHandle? @@ -80,6 +74,8 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol { .sink { [weak self] in self?.updateRoomsWithDiffs($0) } .store(in: &cancellables) + setupVisibleRangeObservers() + setupNotificationSettingsSubscription() } @@ -114,38 +110,7 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol { } func updateVisibleRange(_ range: Range) { - if range.upperBound >= rooms.count { - listUpdatesSubscriptionResult?.controller().addOnePage() - } else if range.lowerBound == 0 { - listUpdatesSubscriptionResult?.controller().resetToOnePage() - } - - guard shouldUpdateVisibleRange else { - return - } - - // The scroll view content size based visible range calculations might create large ranges - // This is just a safety check to not overload the backend - var range = range - if range.upperBound - range.lowerBound > SlidingSyncConstants.maximumVisibleRangeSize { - let upperBound = range.lowerBound + SlidingSyncConstants.maximumVisibleRangeSize - range = range.lowerBound..= rooms.count { + listUpdatesSubscriptionResult?.controller().addOnePage() + } else if range.lowerBound == 0 { + listUpdatesSubscriptionResult?.controller().resetToOnePage() + } + } + .store(in: &cancellables) + visibleItemRangePublisher + .throttle(for: 0.5, scheduler: DispatchQueue.main, latest: true) + .filter { [weak self] range in + guard let self else { return false } + return !range.isEmpty && shouldUpdateVisibleRange + } + .compactMap { [weak self] (range: Range) -> [String]? in + guard let self else { return nil } + + // The scroll view content size based visible range calculations might create large ranges + // This is just a safety check to not overload the backend + var range = range + if range.upperBound - range.lowerBound > SlidingSyncConstants.maximumVisibleRangeSize { + let upperBound = range.lowerBound + SlidingSyncConstants.maximumVisibleRangeSize + range = range.lowerBound.. [RoomSummary] { @@ -241,7 +256,7 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol { inviterProxy = RoomMemberProxy(member: inviter) } - let notificationMode = roomInfo.userDefinedNotificationMode.flatMap { RoomNotificationModeProxy.from(roomNotificationMode: $0) } + let notificationMode = roomInfo.cachedUserDefinedNotificationMode.flatMap { RoomNotificationModeProxy.from(roomNotificationMode: $0) } return RoomSummary(roomListItem: roomListItem, id: roomInfo.id, diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProviderProtocol.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProviderProtocol.swift index 73b60db945..18f9dedd54 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProviderProtocol.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProviderProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Services/RoomDirectorySearch/RoomDirectorySearchProxy.swift b/ElementX/Sources/Services/RoomDirectorySearch/RoomDirectorySearchProxy.swift index 73df08f089..a07767bce1 100644 --- a/ElementX/Sources/Services/RoomDirectorySearch/RoomDirectorySearchProxy.swift +++ b/ElementX/Sources/Services/RoomDirectorySearch/RoomDirectorySearchProxy.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Services/RoomDirectorySearch/RoomDirectorySearchProxyProtocol.swift b/ElementX/Sources/Services/RoomDirectorySearch/RoomDirectorySearchProxyProtocol.swift index f55077bc38..19cb2f84a9 100644 --- a/ElementX/Sources/Services/RoomDirectorySearch/RoomDirectorySearchProxyProtocol.swift +++ b/ElementX/Sources/Services/RoomDirectorySearch/RoomDirectorySearchProxyProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/SecureBackup/SecureBackupController.swift b/ElementX/Sources/Services/SecureBackup/SecureBackupController.swift index fad1033a1b..fc6c81256f 100644 --- a/ElementX/Sources/Services/SecureBackup/SecureBackupController.swift +++ b/ElementX/Sources/Services/SecureBackup/SecureBackupController.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Services/SecureBackup/SecureBackupControllerProtocol.swift b/ElementX/Sources/Services/SecureBackup/SecureBackupControllerProtocol.swift index 21396d38a3..11a84a3300 100644 --- a/ElementX/Sources/Services/SecureBackup/SecureBackupControllerProtocol.swift +++ b/ElementX/Sources/Services/SecureBackup/SecureBackupControllerProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Services/Session/UserSession.swift b/ElementX/Sources/Services/Session/UserSession.swift index 881bd60e8f..b2ffd2a5ad 100644 --- a/ElementX/Sources/Services/Session/UserSession.swift +++ b/ElementX/Sources/Services/Session/UserSession.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Services/Session/UserSessionProtocol.swift b/ElementX/Sources/Services/Session/UserSessionProtocol.swift index d47beb2dd0..8cc002eaa0 100644 --- a/ElementX/Sources/Services/Session/UserSessionProtocol.swift +++ b/ElementX/Sources/Services/Session/UserSessionProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxy.swift b/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxy.swift index fa7f2ab4e9..4ae2052ef2 100644 --- a/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxy.swift +++ b/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxy.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxyProtocol.swift b/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxyProtocol.swift index a6a2f12692..9d1e95e22c 100644 --- a/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxyProtocol.swift +++ b/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxyProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift b/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift index 0d763b6cae..c994d8a82e 100644 --- a/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift +++ b/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/GeoURI.swift b/ElementX/Sources/Services/Timeline/GeoURI.swift index e57e918f6c..451df0f015 100644 --- a/ElementX/Sources/Services/Timeline/GeoURI.swift +++ b/ElementX/Sources/Services/Timeline/GeoURI.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import CoreLocation @@ -24,6 +15,10 @@ struct GeoURI: Hashable { let latitude: Double let longitude: Double let uncertainty: Double? + + var bodyMessage: String { + "Location was shared at \(string)" + } // MARK: - Setup diff --git a/ElementX/Sources/Services/Timeline/IntentionalMentions.swift b/ElementX/Sources/Services/Timeline/IntentionalMentions.swift index 31d8c9202b..e6ff925a05 100644 --- a/ElementX/Sources/Services/Timeline/IntentionalMentions.swift +++ b/ElementX/Sources/Services/Timeline/IntentionalMentions.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/RoomTimelineProvider.swift b/ElementX/Sources/Services/Timeline/RoomTimelineProvider.swift index 03fa54ab6b..ce7c96fa33 100644 --- a/ElementX/Sources/Services/Timeline/RoomTimelineProvider.swift +++ b/ElementX/Sources/Services/Timeline/RoomTimelineProvider.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -42,7 +33,7 @@ class RoomTimelineProvider: RoomTimelineProviderProtocol { .eraseToAnyPublisher() } - private(set) var isLive: Bool + let kind: TimelineKind private let membershipChangeSubject = PassthroughSubject() var membershipChangePublisher: AnyPublisher { @@ -54,10 +45,10 @@ class RoomTimelineProvider: RoomTimelineProviderProtocol { roomTimelineObservationToken?.cancel() } - init(timeline: Timeline, isLive: Bool, paginationStatePublisher: AnyPublisher) { + init(timeline: Timeline, kind: TimelineKind, paginationStatePublisher: AnyPublisher) { serialDispatchQueue = DispatchQueue(label: "io.element.elementx.roomtimelineprovider", qos: .utility) itemProxiesSubject = CurrentValueSubject<[TimelineItemProxy], Never>([]) - self.isLive = isLive + self.kind = kind paginationStatePublisher .sink { [weak self] in diff --git a/ElementX/Sources/Services/Timeline/RoomTimelineProviderProtocol.swift b/ElementX/Sources/Services/Timeline/RoomTimelineProviderProtocol.swift index ee84e7fb8a..8efb1275a0 100644 --- a/ElementX/Sources/Services/Timeline/RoomTimelineProviderProtocol.swift +++ b/ElementX/Sources/Services/Timeline/RoomTimelineProviderProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -45,8 +36,8 @@ protocol RoomTimelineProviderProtocol { var itemProxies: [TimelineItemProxy] { get } /// Whether the timeline is back/forward paginating or not (or has reached the start/end of the room). var paginationState: PaginationState { get } - /// Whether or not the provider is for a live timeline. - var isLive: Bool { get } + /// The kind of the timeline + var kind: TimelineKind { get } /// A publisher that signals when changes to the room's membership have occurred through `/sync`. /// /// This is temporary and will be replace by a subscription on the room itself. diff --git a/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift b/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift index 1d452481fe..d4844c8810 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // // periphery:ignore:all @@ -26,8 +17,9 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol { /// An array of timeline items that will be appended in order when ``simulateIncomingItems()`` is called. var incomingItems: [RoomTimelineItemProtocol] = [] - var roomProxy: RoomProxyProtocol? + var roomProxy: JoinedRoomProxyProtocol? var roomID: String { roomProxy?.id ?? "MockRoomIdentifier" } + var timelineKind: TimelineKind let callbacks = PassthroughSubject() @@ -36,7 +28,8 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol { private var client: UITestsSignalling.Client? - init(listenForSignals: Bool = false) { + init(timelineKind: TimelineKind = .live, listenForSignals: Bool = false) { + self.timelineKind = timelineKind callbacks.send(.paginationState(PaginationState(backward: .idle, forward: .timelineEndReached))) callbacks.send(.isLive(true)) diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift index ad727a623f..457020d50d 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -20,7 +11,7 @@ import MatrixRustSDK import UIKit class RoomTimelineController: RoomTimelineControllerProtocol { - private let roomProxy: RoomProxyProtocol + private let roomProxy: JoinedRoomProxyProtocol private let liveTimelineProvider: RoomTimelineProviderProtocol private let timelineItemFactory: RoomTimelineItemFactoryProtocol private let appSettings: AppSettings @@ -41,7 +32,11 @@ class RoomTimelineController: RoomTimelineControllerProtocol { roomProxy.id } - init(roomProxy: RoomProxyProtocol, + var timelineKind: TimelineKind { + liveTimelineProvider.kind + } + + init(roomProxy: JoinedRoomProxyProtocol, timelineProxy: TimelineProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol, @@ -174,12 +169,8 @@ class RoomTimelineController: RoomTimelineControllerProtocol { func toggleReaction(_ reaction: String, to itemID: TimelineItemIdentifier) async { MXLog.info("Toggle reaction in \(roomID)") - guard let eventID = itemID.eventID else { - MXLog.error("Failed toggling reaction: missing eventID") - return - } - - switch await activeTimeline.toggleReaction(reaction, to: eventID) { + + switch await activeTimeline.toggleReaction(reaction, to: itemID) { case .success: MXLog.info("Finished toggling reaction") case .failure(let error): @@ -309,7 +300,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol { // Inform the world that the initial items are loading from the store callbacks.send(.paginationState(.init(backward: .paginating, forward: .paginating))) - callbacks.send(.isLive(activeTimelineProvider.isLive)) + callbacks.send(.isLive(activeTimelineProvider.kind == .live)) updateTimelineItemsCancellable = activeTimelineProvider .updatePublisher @@ -364,7 +355,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol { // Check if we need to add anything to the top of the timeline. switch paginationState.backward { case .timelineEndReached: - if !roomProxy.isEncryptedOneToOneRoom { + if timelineKind != .pinned, !roomProxy.isEncryptedOneToOneRoom { let timelineStart = TimelineStartRoomTimelineItem(name: roomProxy.name) newTimelineItems.insert(timelineStart, at: 0) } diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactory.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactory.swift index 182fe417d5..d090f7d90e 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactory.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactory.swift @@ -1,23 +1,14 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation struct RoomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol { - func buildRoomTimelineController(roomProxy: RoomProxyProtocol, + func buildRoomTimelineController(roomProxy: JoinedRoomProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol) -> RoomTimelineControllerProtocol { RoomTimelineController(roomProxy: roomProxy, @@ -26,4 +17,16 @@ struct RoomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol { timelineItemFactory: timelineItemFactory, appSettings: ServiceLocator.shared.settings) } + + func buildRoomPinnedTimelineController(roomProxy: JoinedRoomProxyProtocol, + timelineItemFactory: RoomTimelineItemFactoryProtocol) async -> RoomTimelineControllerProtocol? { + guard let pinnedEventsTimeline = await roomProxy.pinnedEventsTimeline else { + return nil + } + return RoomTimelineController(roomProxy: roomProxy, + timelineProxy: pinnedEventsTimeline, + initialFocussedEventID: nil, + timelineItemFactory: timelineItemFactory, + appSettings: ServiceLocator.shared.settings) + } } diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactoryProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactoryProtocol.swift index 3a5d9d5512..71746fd849 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactoryProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactoryProtocol.swift @@ -1,26 +1,19 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @MainActor protocol RoomTimelineControllerFactoryProtocol { - func buildRoomTimelineController(roomProxy: RoomProxyProtocol, + func buildRoomTimelineController(roomProxy: JoinedRoomProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol) -> RoomTimelineControllerProtocol + func buildRoomPinnedTimelineController(roomProxy: JoinedRoomProxyProtocol, + timelineItemFactory: RoomTimelineItemFactoryProtocol) async -> RoomTimelineControllerProtocol? } // sourcery: AutoMockable diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift index 832b7e539e..4ea6719dde 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -38,6 +29,7 @@ enum RoomTimelineControllerError: Error { @MainActor protocol RoomTimelineControllerProtocol { var roomID: String { get } + var timelineKind: TimelineKind { get } var timelineItems: [RoomTimelineItemProtocol] { get } var callbacks: PassthroughSubject { get } diff --git a/ElementX/Sources/Services/Timeline/TimelineItemContent/AggregratedReaction.swift b/ElementX/Sources/Services/Timeline/TimelineItemContent/AggregratedReaction.swift index d17f813e6a..8baf77db5d 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemContent/AggregratedReaction.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemContent/AggregratedReaction.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItemContent/CustomStringConvertible.swift b/ElementX/Sources/Services/Timeline/TimelineItemContent/CustomStringConvertible.swift index 0ef77ac144..5017baaa57 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemContent/CustomStringConvertible.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemContent/CustomStringConvertible.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import MatrixRustSDK diff --git a/ElementX/Sources/Services/Timeline/TimelineItemContent/EncryptionAuthenticity.swift b/ElementX/Sources/Services/Timeline/TimelineItemContent/EncryptionAuthenticity.swift index 78df4fbd5e..847e0ce9d5 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemContent/EncryptionAuthenticity.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemContent/EncryptionAuthenticity.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound @@ -28,6 +19,7 @@ enum EncryptionAuthenticity: Hashable { case unknownDevice(color: Color) case unsignedDevice(color: Color) case unverifiedIdentity(color: Color) + case previouslyVerified(color: Color) case sentInClear(color: Color) var message: String { @@ -40,6 +32,8 @@ enum EncryptionAuthenticity: Hashable { L10n.eventShieldReasonUnsignedDevice case .unverifiedIdentity: L10n.eventShieldReasonUnverifiedIdentity + case .previouslyVerified: + L10n.eventShieldReasonPreviouslyVerified case .sentInClear: L10n.eventShieldReasonSentInClear } @@ -51,6 +45,7 @@ enum EncryptionAuthenticity: Hashable { .unknownDevice(let color), .unsignedDevice(let color), .unverifiedIdentity(let color), + .previouslyVerified(let color), .sentInClear(let color): color } @@ -59,7 +54,7 @@ enum EncryptionAuthenticity: Hashable { var icon: KeyPath { switch self { case .notGuaranteed: \.info - case .unknownDevice, .unsignedDevice, .unverifiedIdentity: \.helpSolid + case .unknownDevice, .unsignedDevice, .unverifiedIdentity, .previouslyVerified: \.helpSolid case .sentInClear: \.lockOff } } @@ -87,6 +82,8 @@ extension EncryptionAuthenticity { self = .unsignedDevice(color: color) case .unverifiedIdentity: self = .unverifiedIdentity(color: color) + case .previouslyVerified: + self = .previouslyVerified(color: color) case .sentInClear: self = .sentInClear(color: color) } diff --git a/ElementX/Sources/Services/Timeline/TimelineItemContent/ReadReceipt.swift b/ElementX/Sources/Services/Timeline/TimelineItemContent/ReadReceipt.swift index 546e26a5ca..990d0fb668 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemContent/ReadReceipt.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemContent/ReadReceipt.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItemContent/RoomTimelineItemProperties.swift b/ElementX/Sources/Services/Timeline/TimelineItemContent/RoomTimelineItemProperties.swift index 07b971bdbf..4b725f3f23 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemContent/RoomTimelineItemProperties.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemContent/RoomTimelineItemProperties.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItemContent/TimelineItemReplyDetails.swift b/ElementX/Sources/Services/Timeline/TimelineItemContent/TimelineItemReplyDetails.swift index de0b171736..9b0e9c2862 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemContent/TimelineItemReplyDetails.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemContent/TimelineItemReplyDetails.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift index 77f5466fb6..6a94a3614b 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -68,7 +59,32 @@ enum TimelineItemProxy { enum TimelineItemDeliveryStatus: Hashable { case sending case sent - case sendingFailed + case sendingFailed(TimelineItemSendFailure) + + var isSendingFailed: Bool { + switch self { + case .sending, .sent: false + case .sendingFailed: true + } + } +} + +/// The reason a timeline item failed to send. +enum TimelineItemSendFailure: Hashable { + enum VerifiedUser: Hashable { + case hasUnsignedDevice(devices: [String: [String]]) + case changedIdentity(users: [String]) + + var affectedUserIDs: [String] { + switch self { + case .hasUnsignedDevice(let devices): Array(devices.keys) + case .changedIdentity(let users): users + } + } + } + + case verifiedUser(VerifiedUser) + case unknown } /// A light wrapper around event timeline items returned from Rust. @@ -88,11 +104,17 @@ class EventTimelineItemProxy { switch localSendState { case .sendingFailed(_, let isRecoverable): - return isRecoverable ? .sending : .sendingFailed + return isRecoverable ? .sending : .sendingFailed(.unknown) case .notSentYet: return .sending case .sent: return .sent + case .verifiedUserHasUnsignedDevice(devices: let devices): + return .sendingFailed(.verifiedUser(.hasUnsignedDevice(devices: devices))) + case .verifiedUserChangedIdentity(users: let users): + return .sendingFailed(.verifiedUser(.changedIdentity(users: users))) + case .crossSigningNotSetup, .sendingFromUnverifiedDevice: + return .sendingFailed(.unknown) } }() diff --git a/ElementX/Sources/Services/Timeline/TimelineItemSender.swift b/ElementX/Sources/Services/Timeline/TimelineItemSender.swift index 3bb75980b4..d0491c7896 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemSender.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemSender.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UIKit diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/DecorationTimelineItemProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineItems/DecorationTimelineItemProtocol.swift index 9c604f27cd..737a8f2d9d 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/DecorationTimelineItemProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/DecorationTimelineItemProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedMessageTimelineItemProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedMessageTimelineItemProtocol.swift index c8c42ec6e2..ce91fe8df0 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedMessageTimelineItemProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedMessageTimelineItemProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedTimelineItemProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedTimelineItemProtocol.swift index d017409f54..aa99847b79 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedTimelineItemProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedTimelineItemProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -56,7 +47,7 @@ extension EventBasedTimelineItemProtocol { } var hasFailedToSend: Bool { - properties.deliveryStatus == .sendingFailed + properties.deliveryStatus?.isSendingFailed == true } var hasFailedDecryption: Bool { diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/AudioRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/AudioRoomTimelineItem.swift index 9ab40821bd..6d99259b46 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/AudioRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/AudioRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/AudioRoomTimelineItemContent.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/AudioRoomTimelineItemContent.swift index f58882dd8e..6353b619e1 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/AudioRoomTimelineItemContent.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/AudioRoomTimelineItemContent.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UIKit diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/EmoteRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/EmoteRoomTimelineItem.swift index 7abe830f2e..0adfaf5c8f 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/EmoteRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/EmoteRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UIKit diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/EmoteRoomTimelineItemContent.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/EmoteRoomTimelineItemContent.swift index 6afb976433..97c88730fe 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/EmoteRoomTimelineItemContent.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/EmoteRoomTimelineItemContent.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UIKit diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/FileRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/FileRoomTimelineItem.swift index c87e95c83f..3b531a7e18 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/FileRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/FileRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UIKit diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/FileRoomTimelineItemContent.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/FileRoomTimelineItemContent.swift index 60139d75b4..9c0cfe9798 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/FileRoomTimelineItemContent.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/FileRoomTimelineItemContent.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/ImageRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/ImageRoomTimelineItem.swift index 91ae1276eb..759e9d4567 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/ImageRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/ImageRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UIKit diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/ImageRoomTimelineItemContent.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/ImageRoomTimelineItemContent.swift index a852ada8c3..0ef2e27aa2 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/ImageRoomTimelineItemContent.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/ImageRoomTimelineItemContent.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/LocationRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/LocationRoomTimelineItem.swift index f21ec5aac8..815c17b1d6 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/LocationRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/LocationRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // struct LocationRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatable { diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/LocationRoomTimelineItemContent.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/LocationRoomTimelineItemContent.swift index df95d316ff..559c88d8e7 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/LocationRoomTimelineItemContent.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/LocationRoomTimelineItemContent.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // struct LocationRoomTimelineItemContent: Hashable { diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/NoticeRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/NoticeRoomTimelineItem.swift index 1833538091..7cee6c0ecb 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/NoticeRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/NoticeRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UIKit diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/NoticeRoomTimelineItemContent.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/NoticeRoomTimelineItemContent.swift index 256b63fe37..9fc67afc61 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/NoticeRoomTimelineItemContent.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/NoticeRoomTimelineItemContent.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UIKit diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/TextRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/TextRoomTimelineItem.swift index 10e5b70991..249d873b03 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/TextRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/TextRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UIKit diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/TextRoomTimelineItemContent.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/TextRoomTimelineItemContent.swift index fff09f07b8..6cc3842fa7 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/TextRoomTimelineItemContent.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/TextRoomTimelineItemContent.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UIKit diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VideoRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VideoRoomTimelineItem.swift index dd5f831c92..896d6a81ff 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VideoRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VideoRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UIKit diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VideoRoomTimelineItemContent.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VideoRoomTimelineItemContent.swift index eb44127ab2..905008a6f3 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VideoRoomTimelineItemContent.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VideoRoomTimelineItemContent.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessageRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessageRoomTimelineItem.swift index 780576d04e..22837d2f5e 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessageRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessageRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessages/VoiceMessageRoomPlaybackView.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessages/VoiceMessageRoomPlaybackView.swift index c806ea5ef4..0b5d3354b3 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessages/VoiceMessageRoomPlaybackView.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessages/VoiceMessageRoomPlaybackView.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import DSWaveformImage @@ -107,6 +98,7 @@ struct VoiceMessageRoomPlaybackView_Previews: PreviewProvider, TestablePreview { 0, 0, 0, 0, 0, 3]) static var playerState = AudioPlayerState(id: .timelineItemIdentifier(.random), + title: L10n.commonVoiceMessage, duration: 10.0, waveform: waveform, progress: 0.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 a58679616c..1cde05ca25 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessages/VoiceMessageRoomTimelineView.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessages/VoiceMessageRoomTimelineView.swift @@ -1,24 +1,15 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation import SwiftUI struct VoiceMessageRoomTimelineView: View { - @EnvironmentObject private var context: RoomScreenViewModel.Context + @EnvironmentObject private var context: TimelineViewModel.Context private let timelineItem: VoiceMessageRoomTimelineItem private let playerState: AudioPlayerState @State private var resumePlaybackAfterScrubbing = false @@ -63,7 +54,7 @@ struct VoiceMessageRoomTimelineView: View { } struct VoiceMessageRoomTimelineView_Previews: PreviewProvider, TestablePreview { - static let viewModel = RoomScreenViewModel.mock + static let viewModel = TimelineViewModel.mock static let timelineItemIdentifier = TimelineItemIdentifier.random static let voiceRoomTimelineItem = VoiceMessageRoomTimelineItem(id: timelineItemIdentifier, timestamp: "Now", @@ -79,6 +70,7 @@ struct VoiceMessageRoomTimelineView_Previews: PreviewProvider, TestablePreview { contentType: nil)) static let playerState = AudioPlayerState(id: .timelineItemIdentifier(timelineItemIdentifier), + title: L10n.commonVoiceMessage, duration: 10.0, waveform: EstimatedWaveform.mockWaveform, progress: 0.4) diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/CallInviteRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/CallInviteRoomTimelineItem.swift index 66e135c922..e5b766e0ae 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/CallInviteRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/CallInviteRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/CallNotificationRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/CallNotificationRoomTimelineItem.swift index 492fb4d2da..e252a11de3 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/CallNotificationRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/CallNotificationRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/CollapsibleTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/CollapsibleTimelineItem.swift index 532d92216d..75fa5930a9 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/CollapsibleTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/CollapsibleTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/EncryptedRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/EncryptedRoomTimelineItem.swift index fd545c9c18..8eefe273fe 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/EncryptedRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/EncryptedRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UIKit diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/PollRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/PollRoomTimelineItem.swift index c2bbe54fb4..dbe238b2b1 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/PollRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/PollRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/RedactedRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/RedactedRoomTimelineItem.swift index 7e71d92782..fe2948d728 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/RedactedRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/RedactedRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StateRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StateRoomTimelineItem.swift index 48787675fd..59a7a01b57 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StateRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StateRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UIKit diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StickerRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StickerRoomTimelineItem.swift index 55b3771330..8c64723186 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StickerRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StickerRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UIKit diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/UnsupportedRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/UnsupportedRoomTimelineItem.swift index ff02f075f5..51b4956088 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/UnsupportedRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/UnsupportedRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UIKit diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Virtual/PaginationIndicatorRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Virtual/PaginationIndicatorRoomTimelineItem.swift index f75e27f003..af817de161 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Virtual/PaginationIndicatorRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Virtual/PaginationIndicatorRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Virtual/ReadMarkerRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Virtual/ReadMarkerRoomTimelineItem.swift index 4f62f24aa6..11b974215e 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Virtual/ReadMarkerRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Virtual/ReadMarkerRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Virtual/SeparatorRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Virtual/SeparatorRoomTimelineItem.swift index 176f2ce25f..5a1a28ce2e 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Virtual/SeparatorRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Virtual/SeparatorRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Virtual/TimelineStartRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Virtual/TimelineStartRoomTimelineItem.swift index 05921874d9..3aab2b6ba3 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Virtual/TimelineStartRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Virtual/TimelineStartRoomTimelineItem.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/RoomStateEventStringBuilder.swift b/ElementX/Sources/Services/Timeline/TimelineItems/RoomStateEventStringBuilder.swift index 4394ba6356..f7cc691fb4 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/RoomStateEventStringBuilder.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/RoomStateEventStringBuilder.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import MatrixRustSDK diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift index f48a273e99..018f47b837 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import MatrixRustSDK @@ -24,14 +15,11 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { /// The Matrix ID of the current user. private let userID: String - private let encryptionAuthenticityEnabled: Bool init(userID: String, - encryptionAuthenticityEnabled: Bool, attributedStringBuilder: AttributedStringBuilderProtocol, stateEventStringBuilder: RoomStateEventStringBuilder) { self.userID = userID - self.encryptionAuthenticityEnabled = encryptionAuthenticityEnabled self.attributedStringBuilder = attributedStringBuilder self.stateEventStringBuilder = stateEventStringBuilder } @@ -503,8 +491,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { } private func authenticity(_ shieldState: ShieldState?) -> EncryptionAuthenticity? { - guard encryptionAuthenticityEnabled else { return nil } - return shieldState.flatMap(EncryptionAuthenticity.init) + shieldState.flatMap(EncryptionAuthenticity.init) } // MARK: - Message events content diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactoryProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactoryProtocol.swift index 78e61a4a4d..8ef6b4aec4 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactoryProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactoryProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemProtocol.swift index 626514fb60..f1bf2b6407 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemView.swift b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemView.swift index b5fd2dccd3..bfc799356b 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemView.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemView.swift @@ -1,22 +1,13 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI struct RoomTimelineItemView: View { - @Environment(\.roomContext) var context + @Environment(\.timelineContext) var context @ObservedObject var viewState: RoomTimelineItemViewState var body: some View { @@ -73,7 +64,9 @@ struct RoomTimelineItemView: View { case .poll(let item): PollRoomTimelineView(timelineItem: item) case .voice(let item): - VoiceMessageRoomTimelineView(timelineItem: item, playerState: context?.viewState.audioPlayerStateProvider?(item.id) ?? AudioPlayerState(id: .timelineItemIdentifier(item.id), duration: 0)) + VoiceMessageRoomTimelineView(timelineItem: item, playerState: context?.viewState.audioPlayerStateProvider?(item.id) ?? AudioPlayerState(id: .timelineItemIdentifier(item.id), + title: L10n.commonVoiceMessage, + duration: 0)) case .callInvite(let item): CallInviteRoomTimelineView(timelineItem: item) case .callNotification(let item): diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemViewState.swift b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemViewState.swift index 99bd864c86..d3ae948287 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemViewState.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemViewState.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/TextBasedRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/TextBasedRoomTimelineItem.swift new file mode 100644 index 0000000000..88461232b8 --- /dev/null +++ b/ElementX/Sources/Services/Timeline/TimelineItems/TextBasedRoomTimelineItem.swift @@ -0,0 +1,10 @@ +// +// 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 + +protocol TextBasedRoomTimelineItem: EventBasedMessageTimelineItemProtocol { } diff --git a/ElementX/Sources/Services/Timeline/TimelineProxy.swift b/ElementX/Sources/Services/Timeline/TimelineProxy.swift index 38c106f623..a3bee43fdc 100644 --- a/ElementX/Sources/Services/Timeline/TimelineProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineProxy.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -27,7 +18,7 @@ final class TimelineProxy: TimelineProxyProtocol { private let backPaginationStatusSubject = CurrentValueSubject(.timelineEndReached) private let forwardPaginationStatusSubject = CurrentValueSubject(.timelineEndReached) - let isLive: Bool + private let kind: TimelineKind private var innerTimelineProvider: RoomTimelineProviderProtocol! var timelineProvider: RoomTimelineProviderProtocol { @@ -38,9 +29,9 @@ final class TimelineProxy: TimelineProxyProtocol { backPaginationStatusObservationToken?.cancel() } - init(timeline: Timeline, isLive: Bool) { + init(timeline: Timeline, kind: TimelineKind) { self.timeline = timeline - self.isLive = isLive + self.kind = kind } func subscribeForUpdates() async { @@ -56,12 +47,16 @@ final class TimelineProxy: TimelineProxyProtocol { await subscribeToPagination() - let provider = await RoomTimelineProvider(timeline: timeline, isLive: isLive, paginationStatePublisher: paginationStatePublisher) + let provider = await RoomTimelineProvider(timeline: timeline, kind: kind, paginationStatePublisher: paginationStatePublisher) // Make sure the existing items are built so that we have content in the timeline before // determining whether or not the timeline should paginate to load more items. await provider.waitForInitialItems() innerTimelineProvider = provider + + Task { + await timeline.fetchMembers() + } } func fetchDetails(for eventID: String) { @@ -84,15 +79,21 @@ final class TimelineProxy: TimelineProxyProtocol { // We can't subscribe to back pagination on detached timelines and as live timelines // can be shared between multiple instances of the same room on the stack, it is // safer to still use the subscription logic for back pagination when live. - await if isLive { - paginateBackwardsOnLive(requestSize: requestSize) - } else { - focussedPaginate(.backwards, requestSize: requestSize) + switch kind { + case .live: + return await paginateBackwardsOnLive(requestSize: requestSize) + case .detached: + return await focussedPaginate(.backwards, requestSize: requestSize) + case .pinned: + return .success(()) } } func paginateForwards(requestSize: UInt16) async -> Result { - await focussedPaginate(.forwards, requestSize: requestSize) + guard kind != .pinned else { + return .success(()) + } + return await focussedPaginate(.forwards, requestSize: requestSize) } /// Paginate backwards using the subscription from Rust to drive the pagination state. @@ -129,9 +130,9 @@ final class TimelineProxy: TimelineProxyProtocol { subject.send(.paginating) do { - let timelineEndReached = try await switch direction { - case .backwards: timeline.paginateBackwards(numEvents: requestSize) - case .forwards: timeline.focusedPaginateForwards(numEvents: requestSize) + let timelineEndReached = switch direction { + case .backwards: try await timeline.paginateBackwards(numEvents: requestSize) + case .forwards: try await timeline.focusedPaginateForwards(numEvents: requestSize) } MXLog.info("Finished paginating \(direction.rawValue)") @@ -155,7 +156,7 @@ final class TimelineProxy: TimelineProxyProtocol { func edit(_ timelineItem: EventTimelineItem, newContent: RoomMessageEventContentWithoutRelation) async -> Result { do { - guard try await timeline.edit(item: timelineItem, newContent: newContent) == true else { + guard try await timeline.edit(item: timelineItem, newContent: .roomMessage(content: newContent)) == true else { return .failure(.failedEditing) } @@ -420,15 +421,15 @@ final class TimelineProxy: TimelineProxyProtocol { } } - func toggleReaction(_ reaction: String, to eventID: String) async -> Result { - MXLog.info("Toggling reaction for eventID: \(eventID)") + func toggleReaction(_ reaction: String, to itemID: TimelineItemIdentifier) async -> Result { + MXLog.info("Toggling reaction for event: \(itemID)") do { - try await timeline.toggleReaction(eventId: eventID, key: reaction) - MXLog.info("Finished toggling reaction for eventID: \(eventID)") + try await timeline.toggleReaction(uniqueId: itemID.timelineID, key: reaction) + MXLog.info("Finished toggling reaction for event: \(itemID)") return .success(()) } catch { - MXLog.error("Failed toggling reaction for eventID: \(eventID)") + MXLog.error("Failed toggling reaction for event: \(itemID)") return .failure(.sdkError(error)) } } @@ -459,7 +460,13 @@ final class TimelineProxy: TimelineProxyProtocol { do { let originalEvent = try await timeline.getEventTimelineItemByEventId(eventId: eventID) - try await timeline.editPoll(question: question, answers: answers, maxSelections: 1, pollKind: .init(pollKind: pollKind), editItem: originalEvent) + guard try await timeline.edit(item: originalEvent, + newContent: .pollStart(pollData: .init(question: question, + answers: answers, + maxSelections: 1, + pollKind: .init(pollKind: pollKind)))) else { + return .failure(.failedEditing) + } MXLog.info("Finished editing poll with eventID: \(eventID)") @@ -538,7 +545,8 @@ final class TimelineProxy: TimelineProxyProtocol { } private func subscribeToPagination() async { - if isLive { + switch kind { + case .live: let backPaginationListener = RoomPaginationStatusListener { [weak self] status in guard let self else { return @@ -557,13 +565,15 @@ final class TimelineProxy: TimelineProxyProtocol { } catch { MXLog.error("Failed to subscribe to back pagination status with error: \(error)") } - } else { + forwardPaginationStatusSubject.send(.timelineEndReached) + case .detached: // Detached timelines don't support observation, set the initial state ourself. backPaginationStatusSubject.send(.idle) + forwardPaginationStatusSubject.send(.idle) + case .pinned: + backPaginationStatusSubject.send(.timelineEndReached) + forwardPaginationStatusSubject.send(.timelineEndReached) } - - // Detached timelines don't support observation, set the initial state ourself. - forwardPaginationStatusSubject.send(isLive ? .timelineEndReached : .idle) } } diff --git a/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift index 511c494099..c081388487 100644 --- a/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift @@ -1,23 +1,20 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine import Foundation import MatrixRustSDK +enum TimelineKind { + case live + case detached + case pinned +} + enum TimelineProxyError: Error { case sdkError(Error) @@ -95,7 +92,7 @@ protocol TimelineProxyProtocol { inReplyTo eventID: String?, intentionalMentions: IntentionalMentions) async -> Result - func toggleReaction(_ reaction: String, to eventID: String) async -> Result + func toggleReaction(_ reaction: String, to itemID: TimelineItemIdentifier) async -> Result // Polls func createPoll(question: String, answers: [String], pollKind: Poll.Kind) async -> Result diff --git a/ElementX/Sources/Services/UserSession/RestorationToken.swift b/ElementX/Sources/Services/UserSession/RestorationToken.swift index 59162f9942..9a3256f11e 100644 --- a/ElementX/Sources/Services/UserSession/RestorationToken.swift +++ b/ElementX/Sources/Services/UserSession/RestorationToken.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -19,9 +10,17 @@ import MatrixRustSDK struct RestorationToken: Equatable { let session: MatrixRustSDK.Session - let sessionDirectory: URL + let sessionDirectories: SessionDirectories let passphrase: String? let pusherNotificationClientIdentifier: String? + + enum CodingKeys: CodingKey { + case session + case sessionDirectory + case cacheDirectory + case passphrase + case pusherNotificationClientIdentifier + } } extension RestorationToken: Codable { @@ -29,26 +28,46 @@ extension RestorationToken: Codable { let container = try decoder.container(keyedBy: CodingKeys.self) let session = try container.decode(MatrixRustSDK.Session.self, forKey: .session) - let sessionDirectory = try container.decodeIfPresent(URL.self, forKey: .sessionDirectory) + let dataDirectory = try container.decodeIfPresent(URL.self, forKey: .sessionDirectory) + let cacheDirectory = try container.decodeIfPresent(URL.self, forKey: .cacheDirectory) + + let sessionDirectories = if let dataDirectory { + if let cacheDirectory { + SessionDirectories(dataDirectory: dataDirectory, cacheDirectory: cacheDirectory) + } else { + SessionDirectories(dataDirectory: dataDirectory) + } + } else { + SessionDirectories(userID: session.userId) + } self = try .init(session: session, - sessionDirectory: sessionDirectory ?? .legacySessionDirectory(for: session.userId), + sessionDirectories: sessionDirectories, passphrase: container.decodeIfPresent(String.self, forKey: .passphrase), pusherNotificationClientIdentifier: container.decodeIfPresent(String.self, forKey: .pusherNotificationClientIdentifier)) } + + func encode(to encoder: any Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(session, forKey: .session) + try container.encode(sessionDirectories.dataDirectory, forKey: .sessionDirectory) + try container.encode(sessionDirectories.cacheDirectory, forKey: .cacheDirectory) + try container.encode(passphrase, forKey: .passphrase) + try container.encode(pusherNotificationClientIdentifier, forKey: .pusherNotificationClientIdentifier) + } } extension MatrixRustSDK.Session: Codable { public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) + let slidingSyncProxy = try container.decodeIfPresent(String.self, forKey: .slidingSyncProxy) self = try .init(accessToken: container.decode(String.self, forKey: .accessToken), refreshToken: container.decodeIfPresent(String.self, forKey: .refreshToken), userId: container.decode(String.self, forKey: .userId), deviceId: container.decode(String.self, forKey: .deviceId), homeserverUrl: container.decode(String.self, forKey: .homeserverUrl), oidcData: container.decodeIfPresent(String.self, forKey: .oidcData), - // Note: the proxy is optional now that we support Simplified Sliding Sync. - slidingSyncProxy: container.decodeIfPresent(String.self, forKey: .slidingSyncProxy)) + slidingSyncVersion: slidingSyncProxy.map { .proxy(url: $0) } ?? .native) } public func encode(to encoder: Encoder) throws { @@ -59,7 +78,7 @@ extension MatrixRustSDK.Session: Codable { try container.encode(deviceId, forKey: .deviceId) try container.encode(homeserverUrl, forKey: .homeserverUrl) try container.encode(oidcData, forKey: .oidcData) - try container.encode(slidingSyncProxy, forKey: .slidingSyncProxy) + try container.encode(slidingSyncVersion.proxyURL, forKey: .slidingSyncProxy) } enum CodingKeys: String, CodingKey { @@ -67,17 +86,9 @@ extension MatrixRustSDK.Session: Codable { } } -// MARK: Migrations - -private extension URL { - /// Gets the store directory of a legacy session that hasn't been migrated to the new token format. - /// - /// This should only be used to fill in the missing value when restoring a token as older versions of - /// the SDK set the session directory for us, based on the user's ID. Newer sessions now use a UUID, - /// which is generated app side during authentication. - static func legacySessionDirectory(for userID: String) -> URL { - // Rust sanitises the user ID replacing invalid characters with an _ - let sanitisedUserID = userID.replacingOccurrences(of: ":", with: "_") - return .sessionsBaseDirectory.appendingPathComponent(sanitisedUserID) +private extension SlidingSyncVersion { + var proxyURL: String? { + guard case let .proxy(url) = self else { return nil } + return url } } diff --git a/ElementX/Sources/Services/UserSession/SessionDirectories.swift b/ElementX/Sources/Services/UserSession/SessionDirectories.swift new file mode 100644 index 0000000000..8a93aed129 --- /dev/null +++ b/ElementX/Sources/Services/UserSession/SessionDirectories.swift @@ -0,0 +1,102 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Foundation + +struct SessionDirectories: Hashable, Codable { + let dataDirectory: URL + let cacheDirectory: URL + + var dataPath: String { dataDirectory.path(percentEncoded: false) } + var cachePath: String { cacheDirectory.path(percentEncoded: false) } + + // MARK: Data Management + + /// Removes the directories from disk if they have been created. + func delete() { + do { + if FileManager.default.directoryExists(at: dataDirectory) { + try FileManager.default.removeItem(at: dataDirectory) + } + } catch { + MXLog.failure("Failed deleting the session data: \(error)") + } + do { + if FileManager.default.directoryExists(at: cacheDirectory) { + try FileManager.default.removeItem(at: cacheDirectory) + } + } catch { + MXLog.failure("Failed deleting the session caches: \(error)") + } + } + + /// Deletes the Rust state store and event cache data, leaving the crypto store and both + /// session directories in place along with any other data that may have been written in them. + func deleteTransientUserData() { + do { + let prefix = "matrix-sdk-state" + try deleteFiles(at: dataDirectory, with: prefix) + } catch { + MXLog.failure("Failed clearing state store: \(error)") + } + do { + let prefix = "matrix-sdk-event-cache" + try deleteFiles(at: cacheDirectory, with: prefix) + } catch { + MXLog.failure("Failed clearing event cache store: \(error)") + } + } + + 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) { + try FileManager.default.removeItem(at: url) + } + } +} + +extension SessionDirectories { + /// Creates a fresh set of session directories for a new user. + init() { + let sessionDirectoryName = UUID().uuidString + dataDirectory = .sessionsBaseDirectory.appending(component: sessionDirectoryName) + cacheDirectory = .cachesBaseDirectory.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) + } + + /// 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) + } +} + +extension SessionDirectories: CustomStringConvertible { + var description: String { + "Data: \(dataPath) Caches: \(cachePath)" + } +} + +// MARK: Migrations + +private extension URL { + /// Gets the store directory of a legacy session that hasn't been migrated to the new token format. + /// + /// This should only be used to fill in the missing value when restoring a token as older versions of + /// the SDK set the session directory for us, based on the user's ID. Newer sessions now use a UUID, + /// which is generated app side during authentication. + static func legacySessionDirectory(for userID: String) -> URL { + // Rust sanitises the user ID replacing invalid characters with an _ + let sanitisedUserID = userID.replacingOccurrences(of: ":", with: "_") + return .sessionsBaseDirectory.appendingPathComponent(sanitisedUserID) + } +} diff --git a/ElementX/Sources/Services/UserSession/UserSessionStore.swift b/ElementX/Sources/Services/UserSession/UserSessionStore.swift index c987e708f9..6b7f94908c 100644 --- a/ElementX/Sources/Services/UserSession/UserSessionStore.swift +++ b/ElementX/Sources/Services/UserSession/UserSessionStore.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -23,7 +14,6 @@ class UserSessionStore: UserSessionStoreProtocol { private let appSettings: AppSettings private let networkMonitor: NetworkMonitorProtocol private let appHooks: AppHooks - private let matrixSDKStateKey = "matrix-sdk-state" /// Whether or not there are sessions in the store. var hasSessions: Bool { !keychainController.restorationTokens().isEmpty } @@ -64,24 +54,26 @@ class UserSessionStore: UserSessionStoreProtocol { // On any restoration failure reset the token and restart keychainController.removeRestorationTokenForUsername(credentials.userID) - deleteSessionDirectory(for: credentials) + credentials.restorationToken.sessionDirectories.delete() return .failure(error) } } - func userSession(for client: Client, sessionDirectory: URL, passphrase: String?) async -> Result { + func userSession(for client: Client, sessionDirectories: SessionDirectories, passphrase: String?) async -> Result { do { let session = try client.session() let userID = try client.userId() let clientProxy = await setupProxyForClient(client) keychainController.setRestorationToken(RestorationToken(session: session, - sessionDirectory: sessionDirectory, + sessionDirectories: sessionDirectories, passphrase: passphrase, pusherNotificationClientIdentifier: clientProxy.pusherNotificationClientIdentifier), forUsername: userID) + MXLog.info("Set up session for user \(userID) at: \(sessionDirectories)") + return .success(buildUserSessionWithClient(clientProxy)) } catch { MXLog.error("Failed creating user session with error: \(error)") @@ -95,7 +87,7 @@ class UserSessionStore: UserSessionStoreProtocol { keychainController.removeRestorationTokenForUsername(userID) if let credentials { - deleteSessionDirectory(for: credentials) + credentials.restorationToken.sessionDirectories.delete() } } @@ -104,14 +96,15 @@ class UserSessionStore: UserSessionStoreProtocol { MXLog.error("Failed to clearing caches: Credentials missing") return } - deleteCaches(for: credentials) + credentials.restorationToken.sessionDirectories.deleteTransientUserData() } // MARK: - Private private func buildUserSessionWithClient(_ clientProxy: ClientProxyProtocol) -> UserSessionProtocol { let mediaProvider = MediaProvider(mediaLoader: clientProxy, - imageCache: .onlyInMemory) + imageCache: .onlyInMemory, + networkMonitor: networkMonitor) let voiceMessageMediaManager = VoiceMessageMediaManager(mediaProvider: mediaProvider) @@ -129,10 +122,12 @@ class UserSessionStore: UserSessionStoreProtocol { let builder = ClientBuilder .baseBuilder(httpProxy: URL(string: homeserverURL)?.globalProxy, - slidingSync: appSettings.simplifiedSlidingSyncEnabled ? .simplified : .restored, + slidingSync: .restored, sessionDelegate: keychainController, - appHooks: appHooks) - .sessionPath(path: credentials.restorationToken.sessionDirectory.path(percentEncoded: false)) + appHooks: appHooks, + invisibleCryptoEnabled: appSettings.invisibleCryptoEnabled) + .sessionPaths(dataPath: credentials.restorationToken.sessionDirectories.dataPath, + cachePath: credentials.restorationToken.sessionDirectories.cachePath) .username(username: credentials.userID) .homeserverUrl(url: homeserverURL) .passphrase(passphrase: credentials.restorationToken.passphrase) @@ -142,6 +137,8 @@ class UserSessionStore: UserSessionStoreProtocol { try await client.restoreSession(session: credentials.restorationToken.session) + MXLog.info("Set up session for user \(credentials.userID) at: \(credentials.restorationToken.sessionDirectories)") + return await .success(setupProxyForClient(client)) } catch { MXLog.error("Failed restoring login with error: \(error)") @@ -154,23 +151,4 @@ class UserSessionStore: UserSessionStoreProtocol { networkMonitor: networkMonitor, appSettings: appSettings) } - - private func deleteSessionDirectory(for credentials: KeychainCredentials) { - do { - try FileManager.default.removeItem(at: credentials.restorationToken.sessionDirectory) - } catch { - MXLog.failure("Failed deleting the session data: \(error)") - } - } - - private func deleteCaches(for credentials: KeychainCredentials) { - do { - let sessionDirectoryContents = try FileManager.default.contentsOfDirectory(at: credentials.restorationToken.sessionDirectory, includingPropertiesForKeys: nil) - for url in sessionDirectoryContents where url.path.contains(matrixSDKStateKey) { - try FileManager.default.removeItem(at: url) - } - } catch { - MXLog.failure("Failed clearing caches: \(error)") - } - } } diff --git a/ElementX/Sources/Services/UserSession/UserSessionStoreProtocol.swift b/ElementX/Sources/Services/UserSession/UserSessionStoreProtocol.swift index 5cbf20b658..fd841ae699 100644 --- a/ElementX/Sources/Services/UserSession/UserSessionStoreProtocol.swift +++ b/ElementX/Sources/Services/UserSession/UserSessionStoreProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -40,7 +31,7 @@ protocol UserSessionStoreProtocol { func restoreUserSession() async -> Result /// Creates a user session for a new client from the SDK along with the passphrase used for the data stores. - func userSession(for client: Client, sessionDirectory: URL, passphrase: String?) async -> Result + func userSession(for client: Client, sessionDirectories: SessionDirectories, passphrase: String?) async -> Result /// Logs out of the specified session. func logout(userSession: UserSessionProtocol) diff --git a/ElementX/Sources/Services/Users/UserDiscoverySection.swift b/ElementX/Sources/Services/Users/UserDiscoverySection.swift index 2d94418a9a..86f6ee66a7 100644 --- a/ElementX/Sources/Services/Users/UserDiscoverySection.swift +++ b/ElementX/Sources/Services/Users/UserDiscoverySection.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Users/UserDiscoveryService.swift b/ElementX/Sources/Services/Users/UserDiscoveryService.swift index a0b1d75afb..2e597367c0 100644 --- a/ElementX/Sources/Services/Users/UserDiscoveryService.swift +++ b/ElementX/Sources/Services/Users/UserDiscoveryService.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Users/UserDiscoveryServiceProtocol.swift b/ElementX/Sources/Services/Users/UserDiscoveryServiceProtocol.swift index df1220dc52..f316e3fbc1 100644 --- a/ElementX/Sources/Services/Users/UserDiscoveryServiceProtocol.swift +++ b/ElementX/Sources/Services/Users/UserDiscoveryServiceProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/Users/UserProfileProxy.swift b/ElementX/Sources/Services/Users/UserProfileProxy.swift index dfcd832206..4066a882fe 100644 --- a/ElementX/Sources/Services/Users/UserProfileProxy.swift +++ b/ElementX/Sources/Services/Users/UserProfileProxy.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/VoiceMessage/VoiceMessageCache.swift b/ElementX/Sources/Services/VoiceMessage/VoiceMessageCache.swift index 8b5018b858..fec6333d57 100644 --- a/ElementX/Sources/Services/VoiceMessage/VoiceMessageCache.swift +++ b/ElementX/Sources/Services/VoiceMessage/VoiceMessageCache.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/VoiceMessage/VoiceMessageCacheProtocol.swift b/ElementX/Sources/Services/VoiceMessage/VoiceMessageCacheProtocol.swift index 9551b046e2..8bf29fc79f 100644 --- a/ElementX/Sources/Services/VoiceMessage/VoiceMessageCacheProtocol.swift +++ b/ElementX/Sources/Services/VoiceMessage/VoiceMessageCacheProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/VoiceMessage/VoiceMessageMediaManager.swift b/ElementX/Sources/Services/VoiceMessage/VoiceMessageMediaManager.swift index 6c8ae5ff6e..e3ae2931cc 100644 --- a/ElementX/Sources/Services/VoiceMessage/VoiceMessageMediaManager.swift +++ b/ElementX/Sources/Services/VoiceMessage/VoiceMessageMediaManager.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/VoiceMessage/VoiceMessageMediaManagerProtocol.swift b/ElementX/Sources/Services/VoiceMessage/VoiceMessageMediaManagerProtocol.swift index 99f2877350..cf453da170 100644 --- a/ElementX/Sources/Services/VoiceMessage/VoiceMessageMediaManagerProtocol.swift +++ b/ElementX/Sources/Services/VoiceMessage/VoiceMessageMediaManagerProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorder.swift b/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorder.swift index 1d0c641cef..e907aed2c0 100644 --- a/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorder.swift +++ b/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorder.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -154,7 +145,7 @@ class VoiceMessageRecorder: VoiceMessageRecorderProtocol { return .success(waveformData) } - func sendVoiceMessage(inRoom roomProxy: RoomProxyProtocol, audioConverter: AudioConverterProtocol) async -> Result { + func sendVoiceMessage(inRoom roomProxy: JoinedRoomProxyProtocol, audioConverter: AudioConverterProtocol) async -> Result { guard let url = audioRecorder.audioFileURL else { return .failure(VoiceMessageRecorderError.missingRecordingFile) } @@ -248,7 +239,7 @@ class VoiceMessageRecorder: VoiceMessageRecorderProtocol { } // Build the preview audio player state - previewAudioPlayerState = await AudioPlayerState(id: .recorderPreview, duration: recordingDuration, waveform: EstimatedWaveform(data: [])) + 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) diff --git a/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorderProtocol.swift b/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorderProtocol.swift index ca1d10d978..677233df3f 100644 --- a/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorderProtocol.swift +++ b/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorderProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -47,7 +38,7 @@ protocol VoiceMessageRecorderProtocol { func seekPlayback(to progress: Double) async func deleteRecording() async - func sendVoiceMessage(inRoom roomProxy: RoomProxyProtocol, audioConverter: AudioConverterProtocol) async -> Result + func sendVoiceMessage(inRoom roomProxy: JoinedRoomProxyProtocol, audioConverter: AudioConverterProtocol) async -> Result } // sourcery: AutoMockable diff --git a/ElementX/Sources/UITests/BlankFormCoordinator.swift b/ElementX/Sources/UITests/BlankFormCoordinator.swift index 7a74a48813..4b34a8b88f 100644 --- a/ElementX/Sources/UITests/BlankFormCoordinator.swift +++ b/ElementX/Sources/UITests/BlankFormCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/ElementX/Sources/UITests/UITestsAppCoordinator.swift b/ElementX/Sources/UITests/UITestsAppCoordinator.swift index 81eb828633..ac29d717a4 100644 --- a/ElementX/Sources/UITests/UITestsAppCoordinator.swift +++ b/ElementX/Sources/UITests/UITestsAppCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -120,20 +111,20 @@ class MockScreen: Identifiable { switch id { case .login: let navigationStackCoordinator = NavigationStackCoordinator() - let coordinator = LoginScreenCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(), + let coordinator = LoginScreenCoordinator(parameters: .init(authenticationService: MockAuthenticationService(), analytics: ServiceLocator.shared.analytics, userIndicatorController: ServiceLocator.shared.userIndicatorController)) navigationStackCoordinator.setRootCoordinator(coordinator) return navigationStackCoordinator case .serverSelection: let navigationStackCoordinator = NavigationStackCoordinator() - let coordinator = ServerSelectionScreenCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(), + let coordinator = ServerSelectionScreenCoordinator(parameters: .init(authenticationService: MockAuthenticationService(), userIndicatorController: ServiceLocator.shared.userIndicatorController, isModallyPresented: true)) navigationStackCoordinator.setRootCoordinator(coordinator) return navigationStackCoordinator case .authenticationFlow: - let flowCoordinator = AuthenticationFlowCoordinator(authenticationService: MockAuthenticationServiceProxy(), + let flowCoordinator = AuthenticationFlowCoordinator(authenticationService: MockAuthenticationService(), qrCodeLoginService: QRCodeLoginServiceMock(), bugReportService: BugReportServiceMock(), navigationRootCoordinator: navigationRootCoordinator, @@ -248,13 +239,14 @@ class MockScreen: Identifiable { return navigationStackCoordinator case .roomPlainNoAvatar: let navigationStackCoordinator = NavigationStackCoordinator() - let parameters = RoomScreenCoordinatorParameters(roomProxy: RoomProxyMock(.init(name: "Some room name", avatarURL: nil)), + let parameters = RoomScreenCoordinatorParameters(roomProxy: JoinedRoomProxyMock(.init(name: "Some room name", avatarURL: nil)), timelineController: MockRoomTimelineController(), mediaProvider: MockMediaProvider(), mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), emojiProvider: EmojiProvider(), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), + ongoingCallRoomIDPublisher: .init(.init(nil)), appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, composerDraftService: ComposerDraftServiceMock(.init())) @@ -265,13 +257,14 @@ class MockScreen: Identifiable { let navigationStackCoordinator = NavigationStackCoordinator() let timelineController = MockRoomTimelineController() timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk - let parameters = RoomScreenCoordinatorParameters(roomProxy: RoomProxyMock(.init(name: "New room", avatarURL: URL.picturesDirectory)), + let parameters = RoomScreenCoordinatorParameters(roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: URL.picturesDirectory)), timelineController: timelineController, mediaProvider: MockMediaProvider(), mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), emojiProvider: EmojiProvider(), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), + ongoingCallRoomIDPublisher: .init(.init(nil)), appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, composerDraftService: ComposerDraftServiceMock(.init())) @@ -282,13 +275,14 @@ class MockScreen: Identifiable { let navigationStackCoordinator = NavigationStackCoordinator() let timelineController = MockRoomTimelineController() timelineController.timelineItems = RoomTimelineItemFixtures.default - let parameters = RoomScreenCoordinatorParameters(roomProxy: RoomProxyMock(.init(name: "New room", avatarURL: URL.picturesDirectory)), + let parameters = RoomScreenCoordinatorParameters(roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: URL.picturesDirectory)), timelineController: timelineController, mediaProvider: MockMediaProvider(), mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), emojiProvider: EmojiProvider(), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), + ongoingCallRoomIDPublisher: .init(.init(nil)), appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, composerDraftService: ComposerDraftServiceMock(.init())) @@ -299,13 +293,14 @@ class MockScreen: Identifiable { let navigationStackCoordinator = NavigationStackCoordinator() let timelineController = MockRoomTimelineController() timelineController.timelineItems = RoomTimelineItemFixtures.smallChunkWithReadReceipts - let parameters = RoomScreenCoordinatorParameters(roomProxy: RoomProxyMock(.init(name: "New room", avatarURL: URL.picturesDirectory)), + let parameters = RoomScreenCoordinatorParameters(roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: URL.picturesDirectory)), timelineController: timelineController, mediaProvider: MockMediaProvider(), mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), emojiProvider: EmojiProvider(), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), + ongoingCallRoomIDPublisher: .init(.init(nil)), appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, composerDraftService: ComposerDraftServiceMock(.init())) @@ -319,13 +314,14 @@ class MockScreen: Identifiable { timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk timelineController.backPaginationResponses = [RoomTimelineItemFixtures.singleMessageChunk] timelineController.incomingItems = [RoomTimelineItemFixtures.incomingMessage] - let parameters = RoomScreenCoordinatorParameters(roomProxy: RoomProxyMock(.init(name: "Small timeline", avatarURL: URL.picturesDirectory)), + let parameters = RoomScreenCoordinatorParameters(roomProxy: JoinedRoomProxyMock(.init(name: "Small timeline", avatarURL: URL.picturesDirectory)), timelineController: timelineController, mediaProvider: MockMediaProvider(), mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), emojiProvider: EmojiProvider(), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), + ongoingCallRoomIDPublisher: .init(.init(nil)), appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, composerDraftService: ComposerDraftServiceMock(.init())) @@ -339,13 +335,14 @@ class MockScreen: Identifiable { let timelineController = MockRoomTimelineController(listenForSignals: true) timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk timelineController.backPaginationResponses = [RoomTimelineItemFixtures.largeChunk] - let parameters = RoomScreenCoordinatorParameters(roomProxy: RoomProxyMock(.init(name: "Small timeline, paginating", avatarURL: URL.picturesDirectory)), + let parameters = RoomScreenCoordinatorParameters(roomProxy: JoinedRoomProxyMock(.init(name: "Small timeline, paginating", avatarURL: URL.picturesDirectory)), timelineController: timelineController, mediaProvider: MockMediaProvider(), mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), emojiProvider: EmojiProvider(), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), + ongoingCallRoomIDPublisher: .init(.init(nil)), appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, composerDraftService: ComposerDraftServiceMock(.init())) @@ -359,13 +356,14 @@ class MockScreen: Identifiable { let timelineController = MockRoomTimelineController(listenForSignals: true) timelineController.timelineItems = RoomTimelineItemFixtures.largeChunk timelineController.backPaginationResponses = [RoomTimelineItemFixtures.largeChunk] - let parameters = RoomScreenCoordinatorParameters(roomProxy: RoomProxyMock(.init(name: "Large timeline", avatarURL: URL.picturesDirectory)), + let parameters = RoomScreenCoordinatorParameters(roomProxy: JoinedRoomProxyMock(.init(name: "Large timeline", avatarURL: URL.picturesDirectory)), timelineController: timelineController, mediaProvider: MockMediaProvider(), mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), emojiProvider: EmojiProvider(), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), + ongoingCallRoomIDPublisher: .init(.init(nil)), appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, composerDraftService: ComposerDraftServiceMock(.init())) @@ -380,13 +378,14 @@ class MockScreen: Identifiable { timelineController.timelineItems = RoomTimelineItemFixtures.largeChunk timelineController.backPaginationResponses = [RoomTimelineItemFixtures.largeChunk] timelineController.incomingItems = [RoomTimelineItemFixtures.incomingMessage] - let parameters = RoomScreenCoordinatorParameters(roomProxy: RoomProxyMock(.init(name: "Large timeline", avatarURL: URL.picturesDirectory)), + let parameters = RoomScreenCoordinatorParameters(roomProxy: JoinedRoomProxyMock(.init(name: "Large timeline", avatarURL: URL.picturesDirectory)), timelineController: timelineController, mediaProvider: MockMediaProvider(), mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), emojiProvider: EmojiProvider(), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), + ongoingCallRoomIDPublisher: .init(.init(nil)), appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, composerDraftService: ComposerDraftServiceMock(.init())) @@ -400,13 +399,14 @@ class MockScreen: Identifiable { let timelineController = MockRoomTimelineController(listenForSignals: true) timelineController.timelineItems = RoomTimelineItemFixtures.largeChunk timelineController.incomingItems = [RoomTimelineItemFixtures.incomingMessage] - let parameters = RoomScreenCoordinatorParameters(roomProxy: RoomProxyMock(.init(name: "Large timeline", avatarURL: URL.picturesDirectory)), + let parameters = RoomScreenCoordinatorParameters(roomProxy: JoinedRoomProxyMock(.init(name: "Large timeline", avatarURL: URL.picturesDirectory)), timelineController: timelineController, mediaProvider: MockMediaProvider(), mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), emojiProvider: EmojiProvider(), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), + ongoingCallRoomIDPublisher: .init(.init(nil)), appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, composerDraftService: ComposerDraftServiceMock(.init())) @@ -419,13 +419,14 @@ class MockScreen: Identifiable { let timelineController = MockRoomTimelineController() timelineController.timelineItems = RoomTimelineItemFixtures.permalinkChunk - let parameters = RoomScreenCoordinatorParameters(roomProxy: RoomProxyMock(.init(name: "Timeline highlight", avatarURL: URL.picturesDirectory)), + let parameters = RoomScreenCoordinatorParameters(roomProxy: JoinedRoomProxyMock(.init(name: "Timeline highlight", avatarURL: URL.picturesDirectory)), timelineController: timelineController, mediaProvider: MockMediaProvider(), mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), emojiProvider: EmojiProvider(), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), + ongoingCallRoomIDPublisher: .init(.init(nil)), appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, composerDraftService: ComposerDraftServiceMock(.init())) @@ -436,7 +437,7 @@ class MockScreen: Identifiable { let client = try UITestsSignalling.Client(mode: .app) client.signals.sink { [weak self] signal in guard case .timeline(.focusOnEvent(let eventID)) = signal else { return } - coordinator.focusOnEvent(eventID: eventID) + coordinator.focusOnEvent(.init(eventID: eventID, shouldSetPin: false)) try? client.send(.success) } .store(in: &cancellables) @@ -452,13 +453,14 @@ class MockScreen: Identifiable { let timelineController = MockRoomTimelineController() timelineController.timelineItems = RoomTimelineItemFixtures.disclosedPolls timelineController.incomingItems = [] - let parameters = RoomScreenCoordinatorParameters(roomProxy: RoomProxyMock(.init(name: "Polls timeline", avatarURL: URL.picturesDirectory)), + let parameters = RoomScreenCoordinatorParameters(roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: URL.picturesDirectory)), timelineController: timelineController, mediaProvider: MockMediaProvider(), mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), emojiProvider: EmojiProvider(), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), + ongoingCallRoomIDPublisher: .init(.init(nil)), appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, composerDraftService: ComposerDraftServiceMock(.init())) @@ -472,13 +474,14 @@ class MockScreen: Identifiable { let timelineController = MockRoomTimelineController() timelineController.timelineItems = RoomTimelineItemFixtures.undisclosedPolls timelineController.incomingItems = [] - let parameters = RoomScreenCoordinatorParameters(roomProxy: RoomProxyMock(.init(name: "Polls timeline", avatarURL: URL.picturesDirectory)), + let parameters = RoomScreenCoordinatorParameters(roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: URL.picturesDirectory)), timelineController: timelineController, mediaProvider: MockMediaProvider(), mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), emojiProvider: EmojiProvider(), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), + ongoingCallRoomIDPublisher: .init(.init(nil)), appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, composerDraftService: ComposerDraftServiceMock(.init())) @@ -492,13 +495,14 @@ class MockScreen: Identifiable { let timelineController = MockRoomTimelineController() timelineController.timelineItems = RoomTimelineItemFixtures.outgoingPolls timelineController.incomingItems = [] - let parameters = RoomScreenCoordinatorParameters(roomProxy: RoomProxyMock(.init(name: "Polls timeline", avatarURL: URL.picturesDirectory)), + let parameters = RoomScreenCoordinatorParameters(roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: URL.picturesDirectory)), timelineController: timelineController, mediaProvider: MockMediaProvider(), mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), emojiProvider: EmojiProvider(), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), + ongoingCallRoomIDPublisher: .init(.init(nil)), appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, composerDraftService: ComposerDraftServiceMock(.init())) @@ -518,7 +522,6 @@ class MockScreen: Identifiable { let navigationSplitCoordinator = NavigationSplitCoordinator(placeholderCoordinator: PlaceholderScreenCoordinator()) let clientProxy = ClientProxyMock(.init(userID: "@mock:client.com", deviceID: "MOCKCLIENT", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))))) - ServiceLocator.shared.settings.migratedAccounts[clientProxy.userID] = true let appMediator = AppMediatorMock.default appMediator.underlyingWindowManager = windowManager @@ -546,7 +549,7 @@ class MockScreen: Identifiable { let navigationStackCoordinator = NavigationStackCoordinator() let members: [RoomMemberProxyMock] = [.mockInvitedAlice, .mockBob, .mockCharlie] let coordinator = RoomMembersListScreenCoordinator(parameters: .init(mediaProvider: MockMediaProvider(), - roomProxy: RoomProxyMock(.init(name: "test", members: members)), + roomProxy: JoinedRoomProxyMock(.init(name: "test", members: members)), userIndicatorController: ServiceLocator.shared.userIndicatorController, analytics: ServiceLocator.shared.analytics)) navigationStackCoordinator.setRootCoordinator(coordinator) @@ -554,7 +557,7 @@ class MockScreen: Identifiable { case .roomRolesAndPermissionsFlow: let navigationStackCoordinator = NavigationStackCoordinator() navigationStackCoordinator.setRootCoordinator(BlankFormCoordinator()) - let coordinator = RoomRolesAndPermissionsFlowCoordinator(parameters: .init(roomProxy: RoomProxyMock(.init(members: .allMembersAsAdmin)), + let coordinator = RoomRolesAndPermissionsFlowCoordinator(parameters: .init(roomProxy: JoinedRoomProxyMock(.init(members: .allMembersAsAdmin)), mediaProvider: MockMediaProvider(), navigationStackCoordinator: navigationStackCoordinator, userIndicatorController: ServiceLocator.shared.userIndicatorController, @@ -627,17 +630,14 @@ class MockScreen: Identifiable { let clientProxy = ClientProxyMock(.init(userID: "@mock:client.com", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))))) - let roomProxy = RoomProxyMock(.init(id: "whatever", name: "okay", shouldUseAutoUpdatingTimeline: true)) - - clientProxy.roomForIdentifierReturnValue = roomProxy + let roomProxy = JoinedRoomProxyMock(.init(id: "whatever", name: "okay", shouldUseAutoUpdatingTimeline: true)) - ServiceLocator.shared.settings.migratedAccounts[clientProxy.userID] = true + clientProxy.roomForIdentifierReturnValue = .joined(roomProxy) let timelineController = RoomTimelineController(roomProxy: roomProxy, timelineProxy: roomProxy.timeline, initialFocussedEventID: nil, timelineItemFactory: RoomTimelineItemFactory(userID: "@alice:matrix.org", - encryptionAuthenticityEnabled: true, attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), stateEventStringBuilder: RoomStateEventStringBuilder(userID: "@alice:matrix.org")), appSettings: ServiceLocator.shared.settings) diff --git a/ElementX/Sources/UITests/UITestsNotificationCenter.swift b/ElementX/Sources/UITests/UITestsNotificationCenter.swift index 1e3e60a0b5..32c2d8dde4 100644 --- a/ElementX/Sources/UITests/UITestsNotificationCenter.swift +++ b/ElementX/Sources/UITests/UITestsNotificationCenter.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/UITests/UITestsScreenIdentifier.swift b/ElementX/Sources/UITests/UITestsScreenIdentifier.swift index 3cf9fc0ce6..043b0b3778 100644 --- a/ElementX/Sources/UITests/UITestsScreenIdentifier.swift +++ b/ElementX/Sources/UITests/UITestsScreenIdentifier.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/ElementX/Sources/UITests/UITestsSignalling.swift b/ElementX/Sources/UITests/UITestsSignalling.swift index 87bb4d9134..84f054e2ef 100644 --- a/ElementX/Sources/UITests/UITestsSignalling.swift +++ b/ElementX/Sources/UITests/UITestsSignalling.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/ElementX/Sources/UnitTests/UnitTestsAppCoordinator.swift b/ElementX/Sources/UnitTests/UnitTestsAppCoordinator.swift index 689d672580..a7db7ea24b 100644 --- a/ElementX/Sources/UnitTests/UnitTestsAppCoordinator.swift +++ b/ElementX/Sources/UnitTests/UnitTestsAppCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SwiftUI diff --git a/ElementX/SupportingFiles/Settings.bundle/Acknowledgements.plist b/ElementX/SupportingFiles/Settings.bundle/Acknowledgements.plist index 64a2fffa6c..a68a19719c 100644 --- a/ElementX/SupportingFiles/Settings.bundle/Acknowledgements.plist +++ b/ElementX/SupportingFiles/Settings.bundle/Acknowledgements.plist @@ -12,9 +12,9 @@ File - Packages/CompoundDesignTokens + Packages/compound-design-tokens Title - CompoundDesignTokens + compound-design-tokens Type PSChildPaneSpecifier @@ -52,9 +52,9 @@ File - Packages/Emojibase + Packages/emojibase-bindings Title - Emojibase + emojibase-bindings Type PSChildPaneSpecifier @@ -108,17 +108,17 @@ File - Packages/MapLibre GL Native + Packages/maplibre-gl-native-distribution Title - MapLibre GL Native + maplibre-gl-native-distribution Type PSChildPaneSpecifier File - Packages/AnalyticsEvents + Packages/matrix-analytics-events Title - AnalyticsEvents + matrix-analytics-events Type PSChildPaneSpecifier @@ -132,33 +132,33 @@ File - Packages/MatrixRustSDK + Packages/matrix-rust-components-swift Title - MatrixRustSDK + matrix-rust-components-swift Type PSChildPaneSpecifier File - Packages/YbridOgg + Packages/ogg-swift Title - YbridOgg + ogg-swift Type PSChildPaneSpecifier File - Packages/YbridOpus + Packages/opus-swift Title - YbridOpus + opus-swift Type PSChildPaneSpecifier File - Packages/PostHog + Packages/posthog-ios Title - PostHog + posthog-ios Type PSChildPaneSpecifier @@ -172,9 +172,9 @@ File - Packages/Sentry + Packages/sentry-cocoa Title - Sentry + sentry-cocoa Type PSChildPaneSpecifier @@ -212,9 +212,9 @@ File - Packages/SwiftOGG + Packages/swift-ogg Title - SwiftOGG + swift-ogg Type PSChildPaneSpecifier @@ -244,9 +244,9 @@ File - Packages/swiftui-introspect + Packages/SwiftUI-Introspect Title - swiftui-introspect + SwiftUI-Introspect Type PSChildPaneSpecifier diff --git a/ElementX/SupportingFiles/Settings.bundle/Packages/AnalyticsEvents.plist b/ElementX/SupportingFiles/Settings.bundle/Packages/compound-design-tokens.plist similarity index 100% rename from ElementX/SupportingFiles/Settings.bundle/Packages/AnalyticsEvents.plist rename to ElementX/SupportingFiles/Settings.bundle/Packages/compound-design-tokens.plist diff --git a/ElementX/SupportingFiles/Settings.bundle/Packages/CompoundDesignTokens.plist b/ElementX/SupportingFiles/Settings.bundle/Packages/emojibase-bindings.plist similarity index 100% rename from ElementX/SupportingFiles/Settings.bundle/Packages/CompoundDesignTokens.plist rename to ElementX/SupportingFiles/Settings.bundle/Packages/emojibase-bindings.plist diff --git a/ElementX/SupportingFiles/Settings.bundle/Packages/MapLibre GL Native.plist b/ElementX/SupportingFiles/Settings.bundle/Packages/maplibre-gl-native-distribution.plist similarity index 100% rename from ElementX/SupportingFiles/Settings.bundle/Packages/MapLibre GL Native.plist rename to ElementX/SupportingFiles/Settings.bundle/Packages/maplibre-gl-native-distribution.plist diff --git a/ElementX/SupportingFiles/Settings.bundle/Packages/Emojibase.plist b/ElementX/SupportingFiles/Settings.bundle/Packages/matrix-analytics-events.plist similarity index 100% rename from ElementX/SupportingFiles/Settings.bundle/Packages/Emojibase.plist rename to ElementX/SupportingFiles/Settings.bundle/Packages/matrix-analytics-events.plist diff --git a/ElementX/SupportingFiles/Settings.bundle/Packages/MatrixRustSDK.plist b/ElementX/SupportingFiles/Settings.bundle/Packages/matrix-rust-components-swift.plist similarity index 100% rename from ElementX/SupportingFiles/Settings.bundle/Packages/MatrixRustSDK.plist rename to ElementX/SupportingFiles/Settings.bundle/Packages/matrix-rust-components-swift.plist diff --git a/ElementX/SupportingFiles/Settings.bundle/Packages/YbridOgg.plist b/ElementX/SupportingFiles/Settings.bundle/Packages/ogg-swift.plist similarity index 100% rename from ElementX/SupportingFiles/Settings.bundle/Packages/YbridOgg.plist rename to ElementX/SupportingFiles/Settings.bundle/Packages/ogg-swift.plist diff --git a/ElementX/SupportingFiles/Settings.bundle/Packages/YbridOpus.plist b/ElementX/SupportingFiles/Settings.bundle/Packages/opus-swift.plist similarity index 100% rename from ElementX/SupportingFiles/Settings.bundle/Packages/YbridOpus.plist rename to ElementX/SupportingFiles/Settings.bundle/Packages/opus-swift.plist diff --git a/ElementX/SupportingFiles/Settings.bundle/Packages/PostHog.plist b/ElementX/SupportingFiles/Settings.bundle/Packages/posthog-ios.plist similarity index 100% rename from ElementX/SupportingFiles/Settings.bundle/Packages/PostHog.plist rename to ElementX/SupportingFiles/Settings.bundle/Packages/posthog-ios.plist diff --git a/ElementX/SupportingFiles/Settings.bundle/Packages/Sentry.plist b/ElementX/SupportingFiles/Settings.bundle/Packages/sentry-cocoa.plist similarity index 100% rename from ElementX/SupportingFiles/Settings.bundle/Packages/Sentry.plist rename to ElementX/SupportingFiles/Settings.bundle/Packages/sentry-cocoa.plist diff --git a/ElementX/SupportingFiles/Settings.bundle/Packages/SwiftOGG.plist b/ElementX/SupportingFiles/Settings.bundle/Packages/swift-ogg.plist similarity index 100% rename from ElementX/SupportingFiles/Settings.bundle/Packages/SwiftOGG.plist rename to ElementX/SupportingFiles/Settings.bundle/Packages/swift-ogg.plist diff --git a/ElementX/SupportingFiles/target.yml b/ElementX/SupportingFiles/target.yml index bdf3347e80..33e3b1b850 100644 --- a/ElementX/SupportingFiles/target.yml +++ b/ElementX/SupportingFiles/target.yml @@ -139,14 +139,26 @@ targets: else echo "warning: SwiftGen not installed, download from https://github.com/SwiftGen/SwiftGen" fi - - name: ๐Ÿง™ Sourcery + - name: ๐Ÿง™ Sourcery - Generate mocks runOnlyWhenInstalling: false basedOnDependencyAnalysis: false shell: /bin/sh script: | export PATH="$PATH:/opt/homebrew/bin" if which sourcery >/dev/null; then - sourcery --config Tools/Sourcery/sourcery_automockable_config.yml + sourcery --config Tools/Sourcery/AutoMockableConfig.yml + else + echo "warning: Sourcery not installed, run swift run tools setup-project" + fi + + - name: ๐Ÿง™ Sourcery - Generate preview tests + runOnlyWhenInstalling: false + basedOnDependencyAnalysis: false + shell: /bin/sh + script: | + export PATH="$PATH:/opt/homebrew/bin" + if which sourcery >/dev/null; then + sourcery --config Tools/Sourcery/PreviewTestsConfig.yml else echo "warning: Sourcery not installed, run swift run tools setup-project" fi @@ -202,7 +214,6 @@ targets: - package: Version - package: Emojibase - package: WysiwygComposer - - package: Prefire - package: SwiftOGG - package: DSWaveformImage product: DSWaveformImageViews diff --git a/IntegrationTests/Sources/Application.swift b/IntegrationTests/Sources/Application.swift index b7084ffa99..a0198f0368 100644 --- a/IntegrationTests/Sources/Application.swift +++ b/IntegrationTests/Sources/Application.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/IntegrationTests/Sources/Common.swift b/IntegrationTests/Sources/Common.swift index 39ea283679..51c334cd34 100644 --- a/IntegrationTests/Sources/Common.swift +++ b/IntegrationTests/Sources/Common.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest @@ -74,15 +65,6 @@ extension XCUIApplication { savePasswordButton.tap() } - - // Migration screen may be shown as an overlay. - // if that pops up soon enough, we just let that happen and wait - let message = staticTexts[A11yIdentifiers.migrationScreen.message] - - if message.waitForExistence(timeout: 10.0) { - currentTestCase.expectation(for: doesNotExistPredicate, evaluatedWith: message) - currentTestCase.waitForExpectations(timeout: 300.0) - } // Wait for the home screen to become visible. let profileButton = buttons[A11yIdentifiers.homeScreen.userAvatar] diff --git a/IntegrationTests/Sources/PerformanceTests.swift b/IntegrationTests/Sources/PerformanceTests.swift deleted file mode 100644 index d5540234c8..0000000000 --- a/IntegrationTests/Sources/PerformanceTests.swift +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import XCTest - -class PerformanceTests: XCTestCase { - func testLoginFlow() throws { - let parser = TestMeasurementParser() - parser.capture(testCase: self) { - let metrics: [XCTMetric] = [ - XCTApplicationLaunchMetric(), - XCTClockMetric(), - XCTOSSignpostMetric(subsystem: Signposter.subsystem, category: Signposter.category, name: "\(Signposter.Name.login)"), - XCTOSSignpostMetric(subsystem: Signposter.subsystem, category: Signposter.category, name: "\(Signposter.Name.firstSync)"), - XCTOSSignpostMetric(subsystem: Signposter.subsystem, category: Signposter.category, name: "\(Signposter.Name.firstRooms)"), - XCTOSSignpostMetric(subsystem: Signposter.subsystem, category: Signposter.category, name: "\(Signposter.Name.roomFlow)") - ] - - self.measure(metrics: metrics) { - self.runLoginLogoutFlow() - } - } - } - - private func runLoginLogoutFlow() { - let app = Application.launch() - - app.login(currentTestCase: self) - - // Open the first room in the list. - let firstRoom = app.buttons.matching(NSPredicate(format: "identifier BEGINSWITH %@", A11yIdentifiers.homeScreen.roomNamePrefix)).firstMatch - XCTAssertTrue(firstRoom.waitForExistence(timeout: 10.0)) - firstRoom.tap() - - // Go back to the room list - let backButton = app.navigationBars.firstMatch.buttons["Chats"] - XCTAssertTrue(backButton.waitForExistence(timeout: 10.0)) - backButton.tap() - - app.logout() - } -} diff --git a/IntegrationTests/Sources/TestMeasurementParser.swift b/IntegrationTests/Sources/TestMeasurementParser.swift index 16f35fcb71..3487f91572 100644 --- a/IntegrationTests/Sources/TestMeasurementParser.swift +++ b/IntegrationTests/Sources/TestMeasurementParser.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/IntegrationTests/Sources/UserFlowTests.swift b/IntegrationTests/Sources/UserFlowTests.swift index 2b4ff790de..46e4e0f085 100644 --- a/IntegrationTests/Sources/UserFlowTests.swift +++ b/IntegrationTests/Sources/UserFlowTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/LICENSE b/LICENSE index 8f71f43fee..be3f7b28e5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,202 +1,661 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/NCE/Sources/NotificationViewController.swift b/NCE/Sources/NotificationViewController.swift index fbe4cddfc1..14b88546ed 100644 --- a/NCE/Sources/NotificationViewController.swift +++ b/NCE/Sources/NotificationViewController.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UIKit diff --git a/NSE/Sources/NotificationContentBuilder.swift b/NSE/Sources/NotificationContentBuilder.swift index 569d90852f..ad01691b4d 100644 --- a/NSE/Sources/NotificationContentBuilder.swift +++ b/NSE/Sources/NotificationContentBuilder.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation @@ -63,6 +54,10 @@ struct NotificationContentBuilder { let notification = UNMutableNotificationContent() notification.receiverID = notificationItem.receiverID notification.roomID = notificationItem.roomID + notification.eventID = switch notificationItem.event { + case .timeline(let event): event.eventId() + case .invite, .none: nil + } notification.sound = notificationItem.isNoisy ? UNNotificationSound(named: UNNotificationSoundName(rawValue: "message.caf")) : nil // So that the UI groups notification that are received for the same room but also for the same user // Removing the @ fixes an iOS bug where the notification crashes if the mute button is tapped @@ -103,9 +98,7 @@ struct NotificationContentBuilder { var notification = try await processCommonRoomMessage(notificationItem: notificationItem, mediaProvider: mediaProvider) let displayName = notificationItem.senderDisplayName ?? notificationItem.roomDisplayName - let message = String(messageEventStringBuilder.buildAttributedString(for: messageType, senderDisplayName: displayName).characters) - - notification.body = notificationItem.hasMention ? L10n.notificationMentionedYouBody(message) : message + notification.body = String(messageEventStringBuilder.buildAttributedString(for: messageType, senderDisplayName: displayName).characters) switch messageType { case .image(content: let content): @@ -153,9 +146,14 @@ struct NotificationContentBuilder { } notification.categoryIdentifier = NotificationConstants.Category.message + let senderName = if let displayName = notificationItem.senderDisplayName { + notificationItem.hasMention ? L10n.notificationSenderMentionReply(displayName) : displayName + } else { + notificationItem.roomDisplayName + } notification = try await notification.addSenderIcon(using: mediaProvider, senderID: notificationItem.senderID, - senderName: notificationItem.senderDisplayName ?? notificationItem.roomDisplayName, + senderName: senderName, icon: icon(for: notificationItem)) return notification } diff --git a/NSE/Sources/NotificationServiceExtension.swift b/NSE/Sources/NotificationServiceExtension.swift index 2164ff6ee0..5443c1ffc3 100644 --- a/NSE/Sources/NotificationServiceExtension.swift +++ b/NSE/Sources/NotificationServiceExtension.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import CallKit @@ -41,7 +32,7 @@ import UserNotifications // We keep a global `environment` singleton to ensure that our app context, // database, logging, etc. are only ever setup once per *process* -private let settings: NSESettingsProtocol = AppSettings() +private let settings: CommonSettingsProtocol = AppSettings() private let notificationContentBuilder = NotificationContentBuilder(messageEventStringBuilder: RoomMessageEventStringBuilder(attributedStringBuilder: AttributedStringBuilder(mentionBuilder: PlainMentionBuilder()), prefix: .none)) private let keychainController = KeychainController(service: .sessions, accessGroup: InfoPlistReader.main.keychainAccessGroupIdentifier) @@ -59,8 +50,8 @@ class NotificationServiceExtension: UNNotificationServiceExtension { override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { guard !DataProtectionManager.isDeviceLockedAfterReboot(containerURL: URL.appGroupContainerDirectory), - let roomId = request.roomId, - let eventId = request.eventId, + let roomID = request.roomID, + let eventID = request.eventID, let clientID = request.pusherNotificationClientIdentifier, let credentials = keychainController.restorationTokens().first(where: { $0.restorationToken.pusherNotificationClientIdentifier == clientID }) else { // We cannot process this notification, it might be due to one of these: @@ -81,15 +72,17 @@ class NotificationServiceExtension: UNNotificationServiceExtension { MXLog.info("\(tag) Payload came: \(request.content.userInfo)") Self.serialQueue.sync { - if Self.userSession == nil { + // If the session directories have changed, the user has logged out and back in (even if they entered the same user ID). + // We can't do this comparison with the access token of the existing session here due to token refresh when using OIDC. + if Self.userSession == nil || Self.userSession?.sessionDirectories != credentials.restorationToken.sessionDirectories { // This function might be run concurrently and from different processes // It's imperative that we create **at most** one UserSession/Client per process Task.synchronous { [appHooks] in do { Self.userSession = try await NSEUserSession(credentials: credentials, clientSessionDelegate: keychainController, - simplifiedSlidingSyncEnabled: settings.simplifiedSlidingSyncEnabled, - appHooks: appHooks) + appHooks: appHooks, + appSettings: settings) } catch { MXLog.error("Failed creating user session with error: \(error)") } @@ -103,8 +96,8 @@ class NotificationServiceExtension: UNNotificationServiceExtension { Task { await run(with: credentials, - roomId: roomId, - eventId: eventId, + roomID: roomID, + eventID: eventID, unreadCount: request.unreadCount) } } @@ -117,10 +110,10 @@ class NotificationServiceExtension: UNNotificationServiceExtension { } private func run(with credentials: KeychainCredentials, - roomId: String, - eventId: String, + roomID: String, + eventID: String, unreadCount: Int?) async { - MXLog.info("\(tag) run with roomId: \(roomId), eventId: \(eventId)") + MXLog.info("\(tag) run with roomId: \(roomID), eventId: \(eventID)") guard let userSession = Self.userSession else { MXLog.error("Invalid NSE User Session, discarding.") @@ -128,7 +121,7 @@ class NotificationServiceExtension: UNNotificationServiceExtension { } do { - guard let itemProxy = await userSession.notificationItemProxy(roomID: roomId, eventID: eventId) else { + guard let itemProxy = await userSession.notificationItemProxy(roomID: roomID, eventID: eventID) else { MXLog.info("\(tag) no notification for the event, discard") return discard(unreadCount: unreadCount) } @@ -137,6 +130,10 @@ class NotificationServiceExtension: UNNotificationServiceExtension { return discard(unreadCount: unreadCount) } + if await handleRedactionNotification(itemProxy) { + return discard(unreadCount: unreadCount) + } + // After the first processing, update the modified content modifiedContent = try await notificationContentBuilder.content(for: itemProxy, mediaProvider: nil) @@ -246,6 +243,29 @@ class NotificationServiceExtension: UNNotificationServiceExtension { return false } + + /// Handles a notification for an `m.room.redaction` event. + /// - Returns: A boolean indicating whether the notification was handled. + private func handleRedactionNotification(_ itemProxy: NotificationItemProxyProtocol) async -> Bool { + guard case let .timeline(event) = itemProxy.event, + case let .messageLike(content) = try? event.eventType(), + case let .roomRedaction(redactedEventID, _) = content else { + return false + } + + guard let redactedEventID else { + MXLog.error("Unable to redact notification due to missing event ID.") + return true // Return true as there's no point showing this notification. + } + + let deliveredNotifications = await UNUserNotificationCenter.current().deliveredNotifications() + + if let targetNotification = deliveredNotifications.first(where: { $0.request.content.eventID == redactedEventID }) { + UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [targetNotification.request.identifier]) + } + + return true + } } // https://stackoverflow.com/a/77300959/730924 diff --git a/NSE/Sources/Other/DataProtectionManager.swift b/NSE/Sources/Other/DataProtectionManager.swift index 059bbc4023..656a922c6f 100644 --- a/NSE/Sources/Other/DataProtectionManager.swift +++ b/NSE/Sources/Other/DataProtectionManager.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/NSE/Sources/Other/NSELogger.swift b/NSE/Sources/Other/NSELogger.swift index b179b8fa81..c0f7cc4f28 100644 --- a/NSE/Sources/Other/NSELogger.swift +++ b/NSE/Sources/Other/NSELogger.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/NSE/Sources/Other/NSESettingsProtocol.swift b/NSE/Sources/Other/NSESettingsProtocol.swift deleted file mode 100644 index c693acc3ba..0000000000 --- a/NSE/Sources/Other/NSESettingsProtocol.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright 2023 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation - -protocol NSESettingsProtocol { - var logLevel: TracingConfiguration.LogLevel { get } - var simplifiedSlidingSyncEnabled: Bool { get } -} - -extension AppSettings: NSESettingsProtocol { } diff --git a/NSE/Sources/Other/NSEUserSession.swift b/NSE/Sources/Other/NSEUserSession.swift index a23f15a6c6..54e915f193 100644 --- a/NSE/Sources/Other/NSEUserSession.swift +++ b/NSE/Sources/Other/NSEUserSession.swift @@ -1,31 +1,27 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation import MatrixRustSDK final class NSEUserSession { + let sessionDirectories: SessionDirectories + private let baseClient: Client private let notificationClient: NotificationClient private let userID: String private(set) lazy var mediaProvider: MediaProviderProtocol = MediaProvider(mediaLoader: MediaLoader(client: baseClient), - imageCache: .onlyOnDisk) + imageCache: .onlyOnDisk, + networkMonitor: nil) private let delegateHandle: TaskHandle? - init(credentials: KeychainCredentials, clientSessionDelegate: ClientSessionDelegate, simplifiedSlidingSyncEnabled: Bool, appHooks: AppHooks) async throws { + init(credentials: KeychainCredentials, clientSessionDelegate: ClientSessionDelegate, appHooks: AppHooks, appSettings: CommonSettingsProtocol) async throws { + sessionDirectories = credentials.restorationToken.sessionDirectories + userID = credentials.userID if credentials.restorationToken.passphrase != nil { MXLog.info("Restoring client with encrypted store.") @@ -35,10 +31,12 @@ final class NSEUserSession { let clientBuilder = ClientBuilder .baseBuilder(setupEncryption: false, httpProxy: URL(string: homeserverURL)?.globalProxy, - slidingSync: simplifiedSlidingSyncEnabled ? .simplified : .restored, + slidingSync: .restored, sessionDelegate: clientSessionDelegate, - appHooks: appHooks) - .sessionPath(path: credentials.restorationToken.sessionDirectory.path(percentEncoded: false)) + appHooks: appHooks, + invisibleCryptoEnabled: appSettings.invisibleCryptoEnabled) + .sessionPaths(dataPath: credentials.restorationToken.sessionDirectories.dataPath, + cachePath: credentials.restorationToken.sessionDirectories.cachePath) .username(username: credentials.userID) .homeserverUrl(url: homeserverURL) .passphrase(passphrase: credentials.restorationToken.passphrase) diff --git a/NSE/Sources/Other/UNNotificationRequest.swift b/NSE/Sources/Other/UNNotificationRequest.swift index 24c7116bb0..6a58537d32 100644 --- a/NSE/Sources/Other/UNNotificationRequest.swift +++ b/NSE/Sources/Other/UNNotificationRequest.swift @@ -1,28 +1,19 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation import UserNotifications extension UNNotificationRequest { - var roomId: String? { + var roomID: String? { content.userInfo[NotificationConstants.UserInfoKey.roomIdentifier] as? String } - var eventId: String? { + var eventID: String? { content.userInfo[NotificationConstants.UserInfoKey.eventIdentifier] as? String } diff --git a/NSE/SupportingFiles/target.yml b/NSE/SupportingFiles/target.yml index fd1492eb62..fae28e976b 100644 --- a/NSE/SupportingFiles/target.yml +++ b/NSE/SupportingFiles/target.yml @@ -40,7 +40,6 @@ targets: - package: DeviceKit - package: DTCoreText - package: LRUCache - - package: Prefire - package: Version info: @@ -73,8 +72,13 @@ targets: sources: - path: ../Sources - path: ../SupportingFiles - - path: ../../ElementX/Sources/Generated + - path: ../../ElementX/Sources/AppHooks/AppHooks.swift + - path: ../../ElementX/Sources/AppHooks/Hooks/ClientBuilderHook.swift + - 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/CurrentValuePublisher.swift - path: ../../ElementX/Sources/Other/Extensions/AttributedString.swift - path: ../../ElementX/Sources/Other/Extensions/Bundle.swift - path: ../../ElementX/Sources/Other/Extensions/ClientBuilder.swift @@ -92,12 +96,14 @@ targets: - path: ../../ElementX/Sources/Other/InfoPlistReader.swift - path: ../../ElementX/Sources/Other/Logging - path: ../../ElementX/Sources/Other/MatrixEntityRegex.swift + - path: ../../ElementX/Sources/Other/NetworkMonitor + - path: ../../ElementX/Sources/Other/Pills/PillConstants.swift + - path: ../../ElementX/Sources/Other/Pills/PlainMentionBuilder.swift - path: ../../ElementX/Sources/Other/SwiftUI/Views/PlaceholderAvatarImage.swift + - path: ../../ElementX/Sources/Other/TestablePreview.swift - path: ../../ElementX/Sources/Other/UserAgentBuilder.swift - path: ../../ElementX/Sources/Other/UserPreference.swift - - path: ../../ElementX/Sources/Other/TestablePreview.swift - - path: ../../ElementX/Sources/Other/Pills/PlainMentionBuilder.swift - - path: ../../ElementX/Sources/Other/Pills/PillConstants.swift + - path: ../../ElementX/Sources/Services/ElementCall/ElementCallServiceConstants.swift - path: ../../ElementX/Sources/Services/Keychain/KeychainController.swift - path: ../../ElementX/Sources/Services/Keychain/KeychainControllerProtocol.swift - path: ../../ElementX/Sources/Services/Media/Provider @@ -105,7 +111,4 @@ targets: - path: ../../ElementX/Sources/Services/Notification/Proxy - path: ../../ElementX/Sources/Services/Room/RoomSummary/RoomMessageEventStringBuilder.swift - path: ../../ElementX/Sources/Services/UserSession/RestorationToken.swift - - path: ../../ElementX/Sources/Services/ElementCall/ElementCallServiceConstants.swift - - path: ../../ElementX/Sources/Application/AppSettings.swift - - path: ../../ElementX/Sources/AppHooks/AppHooks.swift - - path: ../../ElementX/Sources/AppHooks/Hooks/ClientBuilderHook.swift \ No newline at end of file + - path: ../../ElementX/Sources/Services/UserSession/SessionDirectories.swift diff --git a/PreviewTests/.prefire.yml b/PreviewTests/.prefire.yml deleted file mode 100644 index 4c9b913705..0000000000 --- a/PreviewTests/.prefire.yml +++ /dev/null @@ -1,7 +0,0 @@ -test_configuration: - - template_file_path: PreviewTests.stencil - - simulator_device: "iPhone14,6" # iPhone SE 3rd Generation - - required_os: 17 - - snapshot_devices: - - iPhone 15 - - iPad diff --git a/PreviewTests/PreviewTests.stencil b/PreviewTests/PreviewTests.stencil deleted file mode 100644 index 2a16569124..0000000000 --- a/PreviewTests/PreviewTests.stencil +++ /dev/null @@ -1,284 +0,0 @@ -// swiftlint:disable all -// swiftformat:disable all - -import XCTest -import SwiftUI -import Prefire -@testable import SnapshotTesting -#if canImport(AccessibilitySnapshot) - import AccessibilitySnapshot -#endif -{% if argument.mainTarget %} -@testable import {{ argument.mainTarget }} -{% endif %} -{% for import in argument.imports %} -{% if import != "last" %} -import {{ import }} -{% endif %} -{% endfor %} -{% for import in argument.testableImports %} -{% if import != "last" %} -@testable import {{ import }} -{% endif %} -{% endfor %} - -class PreviewTests: XCTestCase { - private let deviceConfig: ViewImageConfig = .iPhoneX - private var simulatorDevice: String?{% if argument.simulatorDevice %} = "{{ argument.simulatorDevice|default:nil }}"{% endif %} - private var requiredOSVersion: Int?{% if argument.simulatorOSVersion %} = {{ argument.simulatorOSVersion }}{% endif %} - private let snapshotDevices: [String]{% if argument.snapshotDevices %} = {{ argument.snapshotDevices|split:"|" }}{% else %} = []{% endif %} - - - {% if argument.file %} - - private var file: StaticString { .init(stringLiteral: "{{ argument.file }}") } - {% endif %} - - override func setUp() { - super.setUp() - - checkEnvironments() - UIView.setAnimationsEnabled(false) - } - - // MARK: - PreviewProvider - - {% for type in types.types where (type.implements.PrefireProvider or type.based.PrefireProvider or type|annotated:"PrefireProvider") and type.name != "TestablePreview" %} - func test_{{ type.name|lowerFirstLetter|replace:"_Previews", "" }}() { - for preview in {{ type.name }}._allPreviews { - assertSnapshots(matching: preview) - } - } - {%- if not forloop.last %} - - {% endif %} - {% endfor %} - {% if argument.previewsMacros %} - // MARK: - Macros - - {{ argument.previewsMacros }} - {% endif %} - // MARK: Private - - private func assertSnapshots(matching preview: _Preview, testName: String = #function) { - guard !snapshotDevices.isEmpty else { - if let failure = assertSnapshots(matching: AnyView(preview.content), - name: preview.displayName, - isScreen: preview.layout == .device, - device: preview.device?.snapshotDevice() ?? deviceConfig, - testName: testName) { - XCTFail(failure) - } - return - } - - for deviceName in snapshotDevices { - guard var device = PreviewDevice(rawValue: deviceName).snapshotDevice() else { - fatalError("Unknown device name: \(deviceName)") - } - - // Ignore specific device safe area (using the workaround value to fix rendering issues). - device.safeArea = .one - - // Ignore specific device display scale - let traits = UITraitCollection(displayScale: 2.0) - - if let failure = assertSnapshots(matching: AnyView(preview.content), - name: preview.displayName, - isScreen: preview.layout == .device, - device: device, - testName: testName + deviceName + "-" + localeCode, - traits: traits) { - XCTFail(failure) - } - } - } - - private var localeCode: String { - if UserDefaults.standard.bool(forKey: "NSDoubleLocalizedStrings") { - return "pseudo" - } - return languageCode + "-" + regionCode - } - - private var languageCode: String { - Locale.current.language.languageCode?.identifier ?? "" - } - - private var regionCode: String { - Locale.current.language.region?.identifier ?? "" - } - - private func assertSnapshots(matching view: AnyView, - name: String?, isScreen: Bool, - device: ViewImageConfig, - testName: String = #function, - traits: UITraitCollection = .init()) -> String? { - var delay: TimeInterval = 0 - var precision: Float = 1 - var perceptualPrecision: Float = 1 - - let view = view - .onPreferenceChange(DelayPreferenceKey.self) { delay = $0 } - .onPreferenceChange(PrecisionPreferenceKey.self) { precision = $0 } - .onPreferenceChange(PerceptualPrecisionPreferenceKey.self) { perceptualPrecision = $0 } - - let matchingView = isScreen ? AnyView(view) : AnyView(view - .frame(width: device.size?.width) - .fixedSize(horizontal: false, vertical: true) - ) - - let failure = verifySnapshot( - of: matchingView, - as: .prefireImage(precision: { precision }, - perceptualPrecision: { perceptualPrecision }, - duration: { delay }, - layout: isScreen ? .device(config: device) : .sizeThatFits, - traits: traits), - named: name{% if argument.file %}, - file: file{% endif %}, - testName: testName - ) - - #if canImport(AccessibilitySnapshot) - let vc = UIHostingController(rootView: matchingView) - vc.view.frame = UIScreen.main.bounds - assertSnapshot( - matching: vc, - as: .wait(for: delay, on: .accessibilityImage(showActivationPoints: .always)), - named: name.flatMap { $0 + ".accessibility" }{% if argument.file %}, - file: file{% endif %}, - testName: testName - ) - #endif - return failure - } - - /// Check environments to avoid problems with snapshots on different devices or OS. - private func checkEnvironments() { - if let simulatorDevice { - let deviceModel = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] - guard deviceModel?.contains(simulatorDevice) ?? false else { - fatalError("\(deviceModel ?? "Unknown") is the wrong one. Switch to using \(simulatorDevice) for these tests.") - } - } - - if let requiredOSVersion { - let osVersion = ProcessInfo().operatingSystemVersion - guard osVersion.majorVersion == requiredOSVersion else { - fatalError("Switch to iOS \(requiredOSVersion) for these tests.") - } - } - } -} - -// MARK: - SnapshotTesting + Extensions - -private extension PreviewDevice { - func snapshotDevice() -> ViewImageConfig? { - switch rawValue { - case "iPhone 15", "iPhone 14", "iPhone 13", "iPhone 12", "iPhone 11", "iPhone 10": - return .iPhoneX - case "iPhone 6", "iPhone 6s", "iPhone 7", "iPhone 8": - return .iPhone8 - case "iPhone 6 Plus", "iPhone 6s Plus", "iPhone 8 Plus": - return .iPhone8Plus - case "iPhone SE (1st generation)", "iPhone SE (2nd generation)": - return .iPhoneSe - case "iPad": - return .iPad10_2 - case "iPad Mini": - return .iPadMini - case "iPad Pro 11": - return .iPadPro11 - case "iPad Pro 12.9": - return .iPadPro12_9 - default: return nil - } - } -} - -private extension Snapshotting where Value: SwiftUI.View, Format == UIImage { - static func prefireImage( - drawHierarchyInKeyWindow: Bool = false, - precision: @escaping () -> Float, - perceptualPrecision: @escaping () -> Float, - duration: @escaping () -> TimeInterval, - layout: SwiftUISnapshotLayout = .sizeThatFits, - traits: UITraitCollection = .init() - ) -> Snapshotting { - let config: ViewImageConfig - - switch layout { - #if os(iOS) || os(tvOS) - case let .device(config: deviceConfig): - config = deviceConfig - #endif - case .sizeThatFits: - // Make sure to use the workaround safe area insets. - config = .init(safeArea: .one, size: nil, traits: traits) - case let .fixed(width: width, height: height): - let size = CGSize(width: width, height: height) - // Make sure to use the workaround safe area insets. - config = .init(safeArea: .one, size: size, traits: traits) - } - - return SimplySnapshotting(pathExtension: "png", diffing: .prefireImage(precision: precision, perceptualPrecision: perceptualPrecision, scale: traits.displayScale)) - .asyncPullback { view in - var config = config - - let controller: UIViewController - - if config.size != nil { - controller = UIHostingController(rootView: view) - } else { - let hostingController = UIHostingController(rootView: view) - - let maxSize = CGSize.zero - config.size = hostingController.sizeThatFits(in: maxSize) - - controller = hostingController - } - - return Async { callback in - let strategy = snapshotView( - config: config, - drawHierarchyInKeyWindow: drawHierarchyInKeyWindow, - traits: traits, - view: controller.view, - viewController: controller - ) - - let duration = duration() - if duration != .zero { - let expectation = XCTestExpectation(description: "Wait") - DispatchQueue.main.asyncAfter(deadline: .now() + duration) { - expectation.fulfill() - } - _ = XCTWaiter.wait(for: [expectation], timeout: duration + 1) - } - strategy.run(callback) - } - } - } -} - -private extension Diffing where Value == UIImage { - static func prefireImage(precision: @escaping () -> Float, perceptualPrecision: @escaping () -> Float, scale: CGFloat?) -> Diffing { - lazy var originalDiffing = Diffing.image(precision: precision(), perceptualPrecision: 0.98, scale: scale) - return Diffing( - toData: { originalDiffing.toData($0) }, - fromData: { originalDiffing.fromData($0) }, - diff: { originalDiffing.diff($0, $1) } - ) - } -} - -private extension UIEdgeInsets { - /// A custom inset that prevents the snapshotting library from rendering the - /// origin at (10000, 10000) which breaks some of our views such as MessageText. - static var one: UIEdgeInsets { UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1) } -} - -// swiftlint:enable all -// swiftformat:enable all diff --git a/PreviewTests/Sources/GeneratedPreviewTests.swift b/PreviewTests/Sources/GeneratedPreviewTests.swift new file mode 100644 index 0000000000..47fb1f5988 --- /dev/null +++ b/PreviewTests/Sources/GeneratedPreviewTests.swift @@ -0,0 +1,982 @@ +// Generated using Sourcery 2.2.5 โ€” https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT + +// swiftlint:disable all +// swiftformat:disable all + +import XCTest +@testable import ElementX + +extension PreviewTests { + + // MARK: - PreviewProvider + + func test_advancedSettingsScreen() { + for preview in AdvancedSettingsScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_analyticsPromptScreenCheckmarkItem() { + for preview in AnalyticsPromptScreenCheckmarkItem_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_analyticsPromptScreen() { + for preview in AnalyticsPromptScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_analyticsSettingsScreen() { + for preview in AnalyticsSettingsScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_appLockScreen() { + for preview in AppLockScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_appLockSetupBiometricsScreen() { + for preview in AppLockSetupBiometricsScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_appLockSetupPINScreen() { + for preview in AppLockSetupPINScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_appLockSetupSettingsScreen() { + for preview in AppLockSetupSettingsScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_audioRoomTimelineView() { + for preview in AudioRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_authenticationStartScreen() { + for preview in AuthenticationStartScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_avatarHeaderView() { + for preview in AvatarHeaderView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_badgeLabel() { + for preview in BadgeLabel_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_blockedUsersScreen() { + for preview in BlockedUsersScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_bugReport() { + for preview in BugReport_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_callInviteRoomTimelineView() { + for preview in CallInviteRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_callNotificationRoomTimelineView() { + for preview in CallNotificationRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_collapsibleRoomTimelineView() { + for preview in CollapsibleRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_completionSuggestion() { + for preview in CompletionSuggestion_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_composerToolbar() { + for preview in ComposerToolbar_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_createRoom() { + for preview in CreateRoom_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_deactivateAccountScreen() { + for preview in DeactivateAccountScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_emojiPickerScreenHeaderView() { + for preview in EmojiPickerScreenHeaderView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_emojiPickerScreen() { + for preview in EmojiPickerScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_emoteRoomTimelineView() { + for preview in EmoteRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_encryptedRoomTimelineView() { + for preview in EncryptedRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_encryptionResetPasswordScreen() { + for preview in EncryptionResetPasswordScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_encryptionResetScreen() { + for preview in EncryptionResetScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_estimatedWaveformView() { + for preview in EstimatedWaveformView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_fileRoomTimelineView() { + for preview in FileRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_formButtonStyles() { + for preview in FormButtonStyles_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_formattedBodyText() { + for preview in FormattedBodyText_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_formattingToolbar() { + for preview in FormattingToolbar_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_fullscreenDialog() { + for preview in FullscreenDialog_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_globalSearchScreenListRow() { + for preview in GlobalSearchScreenListRow_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_globalSearchScreen() { + for preview in GlobalSearchScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_heroImage() { + for preview in HeroImage_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_highlightedTimelineItemModifier() { + for preview in HighlightedTimelineItemModifier_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_homeScreenEmptyStateView() { + for preview in HomeScreenEmptyStateView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_homeScreenInviteCell() { + for preview in HomeScreenInviteCell_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_homeScreenRecoveryKeyConfirmationBanner() { + for preview in HomeScreenRecoveryKeyConfirmationBanner_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_homeScreenRoomCell() { + for preview in HomeScreenRoomCell_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_homeScreenSlidingSyncMigrationBanner() { + for preview in HomeScreenSlidingSyncMigrationBanner_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_homeScreen() { + for preview in HomeScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_identityConfirmationScreen() { + for preview in IdentityConfirmationScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_identityConfirmedScreen() { + for preview in IdentityConfirmedScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_imageRoomTimelineView() { + for preview in ImageRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_inviteUsersScreenSelectedItem() { + for preview in InviteUsersScreenSelectedItem_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_inviteUsersScreen() { + for preview in InviteUsersScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_joinRoomScreen() { + for preview in JoinRoomScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_legalInformationScreen() { + for preview in LegalInformationScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_locationMarkerView() { + for preview in LocationMarkerView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_locationRoomTimelineView() { + for preview in LocationRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_loginScreen() { + for preview in LoginScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_longPressWithFeedback() { + for preview in LongPressWithFeedback_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_mapLibreStaticMapView() { + for preview in MapLibreStaticMapView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_matrixUserPermalink() { + for preview in MatrixUserPermalink_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_mediaUploadPreviewScreen() { + for preview in MediaUploadPreviewScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_mentionSuggestionItemView() { + for preview in MentionSuggestionItemView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_messageComposerTextField() { + for preview in MessageComposerTextField_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_messageComposer() { + for preview in MessageComposer_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_messageForwardingScreen() { + for preview in MessageForwardingScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_messageText() { + for preview in MessageText_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_noticeRoomTimelineView() { + for preview in NoticeRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_notificationPermissionsScreen() { + for preview in NotificationPermissionsScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_notificationSettingsEditScreenRoomCell() { + for preview in NotificationSettingsEditScreenRoomCell_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_notificationSettingsEditScreen() { + for preview in NotificationSettingsEditScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_notificationSettingsScreen() { + for preview in NotificationSettingsScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_pINTextField() { + for preview in PINTextField_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_paginationIndicatorRoomTimelineView() { + for preview in PaginationIndicatorRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_pillView() { + for preview in PillView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_pinnedEventsTimelineScreen() { + for preview in PinnedEventsTimelineScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_pinnedItemsBannerView() { + for preview in PinnedItemsBannerView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_pinnedItemsIndicatorView() { + for preview in PinnedItemsIndicatorView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_placeholderAvatarImage() { + for preview in PlaceholderAvatarImage_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_placeholderScreen() { + for preview in PlaceholderScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_pollFormScreen() { + for preview in PollFormScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_pollOptionView() { + for preview in PollOptionView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_pollRoomTimelineView() { + for preview in PollRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_pollView() { + for preview in PollView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_qRCodeLoginScreen() { + for preview in QRCodeLoginScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_reactionsSummaryView() { + for preview in ReactionsSummaryView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_readMarkerRoomTimelineView() { + for preview in ReadMarkerRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_readReceiptCell() { + for preview in ReadReceiptCell_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_readReceiptsSummaryView() { + for preview in ReadReceiptsSummaryView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_redactedRoomTimelineView() { + for preview in RedactedRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_reportContentScreen() { + for preview in ReportContentScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_resolveVerifiedUserSendFailureScreen() { + for preview in ResolveVerifiedUserSendFailureScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomAttachmentPicker() { + for preview in RoomAttachmentPicker_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomAvatarImage() { + for preview in RoomAvatarImage_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomChangePermissionsScreen() { + for preview in RoomChangePermissionsScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomChangeRolesScreenRow() { + for preview in RoomChangeRolesScreenRow_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomChangeRolesScreenSelectedItem() { + for preview in RoomChangeRolesScreenSelectedItem_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomChangeRolesScreen() { + for preview in RoomChangeRolesScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomDetailsEditScreen() { + for preview in RoomDetailsEditScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomDetailsScreen() { + for preview in RoomDetailsScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomDirectorySearchCell() { + for preview in RoomDirectorySearchCell_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomDirectorySearchScreen() { + for preview in RoomDirectorySearchScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomDirectorySearchView() { + for preview in RoomDirectorySearchView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomHeaderView() { + for preview in RoomHeaderView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomInviterLabel() { + for preview in RoomInviterLabel_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomListFilterView() { + for preview in RoomListFilterView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomListFiltersEmptyStateView() { + for preview in RoomListFiltersEmptyStateView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomListFiltersView() { + for preview in RoomListFiltersView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomMemberDetailsScreen() { + for preview in RoomMemberDetailsScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomMembersListManageMemberSheet() { + for preview in RoomMembersListManageMemberSheet_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomMembersListMemberCell() { + for preview in RoomMembersListMemberCell_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomMembersListScreen() { + for preview in RoomMembersListScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomNotificationSettingsCustomSectionView() { + for preview in RoomNotificationSettingsCustomSectionView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomNotificationSettingsScreen() { + for preview in RoomNotificationSettingsScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomNotificationSettingsUserDefinedScreen() { + for preview in RoomNotificationSettingsUserDefinedScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomPollsHistoryScreen() { + for preview in RoomPollsHistoryScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomRolesAndPermissionsScreen() { + for preview in RoomRolesAndPermissionsScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_roomScreen() { + for preview in RoomScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_sFNumberedListView() { + for preview in SFNumberedListView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_secureBackupKeyBackupScreen() { + for preview in SecureBackupKeyBackupScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_secureBackupLogoutConfirmationScreen() { + for preview in SecureBackupLogoutConfirmationScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_secureBackupRecoveryKeyScreen() { + for preview in SecureBackupRecoveryKeyScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_secureBackupScreen() { + for preview in SecureBackupScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_separatorRoomTimelineView() { + for preview in SeparatorRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_serverConfirmationScreen() { + for preview in ServerConfirmationScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_serverSelection() { + for preview in ServerSelection_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_sessionVerification() { + for preview in SessionVerification_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_settingsScreen() { + for preview in SettingsScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_shimmerOverlay() { + for preview in ShimmerOverlay_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_softLogoutScreen() { + for preview in SoftLogoutScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_splashScreen() { + for preview in SplashScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_startChatScreen() { + for preview in StartChatScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_stateRoomTimelineView() { + for preview in StateRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_staticLocationScreenViewer() { + for preview in StaticLocationScreenViewer_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_stickerRoomTimelineView() { + for preview in StickerRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_swipeRightAction() { + for preview in SwipeRightAction_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_swipeToReplyView() { + for preview in SwipeToReplyView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_textRoomTimelineView() { + for preview in TextRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_threadDecorator() { + for preview in ThreadDecorator_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_timelineDeliveryStatusView() { + for preview in TimelineDeliveryStatusView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_timelineItemBubbledStylerView() { + for preview in TimelineItemBubbledStylerView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_timelineItemDebugView() { + for preview in TimelineItemDebugView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_timelineItemMenu() { + for preview in TimelineItemMenu_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_timelineItemSendInfoLabel() { + for preview in TimelineItemSendInfoLabel_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_timelineItemStyler() { + for preview in TimelineItemStyler_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_timelineReactionView() { + for preview in TimelineReactionView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_timelineReadReceiptsView() { + for preview in TimelineReadReceiptsView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_timelineReplyView() { + for preview in TimelineReplyView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_timelineStartRoomTimelineView() { + for preview in TimelineStartRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_timelineView() { + for preview in TimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_typingIndicatorView() { + for preview in TypingIndicatorView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_unsupportedRoomTimelineView() { + for preview in UnsupportedRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_userDetailsEditScreen() { + for preview in UserDetailsEditScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_userIndicatorModalView() { + for preview in UserIndicatorModalView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_userIndicatorToastView() { + for preview in UserIndicatorToastView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_userProfileCell() { + for preview in UserProfileCell_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_userProfileScreen() { + for preview in UserProfileScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_videoRoomTimelineView() { + for preview in VideoRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_voiceMessageButton() { + for preview in VoiceMessageButton_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_voiceMessagePreviewComposer() { + for preview in VoiceMessagePreviewComposer_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_voiceMessageRecordingButton() { + for preview in VoiceMessageRecordingButton_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_voiceMessageRecordingComposer() { + for preview in VoiceMessageRecordingComposer_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_voiceMessageRecordingView() { + for preview in VoiceMessageRecordingView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_voiceMessageRoomPlaybackView() { + for preview in VoiceMessageRoomPlaybackView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_voiceMessageRoomTimelineView() { + for preview in VoiceMessageRoomTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_waveformCursorView() { + for preview in WaveformCursorView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } +} + +// swiftlint:enable all +// swiftformat:enable all diff --git a/PreviewTests/Sources/PreviewTests.swift b/PreviewTests/Sources/PreviewTests.swift new file mode 100644 index 0000000000..4d7148508d --- /dev/null +++ b/PreviewTests/Sources/PreviewTests.swift @@ -0,0 +1,219 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import SwiftUI +import XCTest + +@testable import ElementX +@testable import SnapshotTesting + +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 snapshotDevices = ["iPhone 16", "iPad"] + private var recordMode: SnapshotTestingConfiguration.Record = .missing + + override func setUp() { + super.setUp() + + if ProcessInfo().environment["RECORD_FAILURES"].map(Bool.init) == true { + recordMode = .failed + } + + checkEnvironments() + UIView.setAnimationsEnabled(false) + } + + /// Check environments to avoid problems with snapshots on different devices or OS. + private func checkEnvironments() { + if let simulatorDevice { + let deviceModel = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] + guard deviceModel?.contains(simulatorDevice) ?? false else { + fatalError("\(deviceModel ?? "Unknown") is the wrong one. Switch to using \(simulatorDevice) for these tests.") + } + } + + let osVersion = ProcessInfo().operatingSystemVersion + guard osVersion.majorVersion == requiredOSVersion.major, osVersion.minorVersion == requiredOSVersion.minor else { + fatalError("Switch to iOS \(requiredOSVersion) for these tests.") + } + guard !snapshotDevices.isEmpty else { + fatalError("Specify at least one snapshot device to test on.") + } + } + + // MARK: - Snapshots + + func assertSnapshots(matching preview: _Preview, testName: String = #function) { + for deviceName in snapshotDevices { + guard var device = PreviewDevice(rawValue: deviceName).snapshotDevice() else { + fatalError("Unknown device name: \(deviceName)") + } + // Ignore specific device safe area (using the workaround value to fix rendering issues). + device.safeArea = .one + // Ignore specific device display scale + let traits = UITraitCollection(displayScale: 2.0) + if let failure = assertSnapshots(matching: AnyView(preview.content), + name: preview.displayName, + isScreen: preview.layout == .device, + device: device, + testName: testName + deviceName + "-" + localeCode, + traits: traits) { + XCTFail(failure) + } + } + } + + private var localeCode: String { + if UserDefaults.standard.bool(forKey: "NSDoubleLocalizedStrings") { + return "pseudo" + } + return languageCode + "-" + regionCode + } + + private var languageCode: String { + Locale.current.language.languageCode?.identifier ?? "" + } + + private var regionCode: String { + Locale.current.language.region?.identifier ?? "" + } + + private func assertSnapshots(matching view: AnyView, + name: String?, isScreen: Bool, + device: ViewImageConfig, + testName: String = #function, + traits: UITraitCollection = .init()) -> String? { + var delay: TimeInterval = 0 + var precision: Float = 1 + var perceptualPrecision: Float = 1 + + let view = view + .onPreferenceChange(SnapshotDelayPreferenceKey.self) { delay = $0 } + .onPreferenceChange(SnapshotPrecisionPreferenceKey.self) { precision = $0 } + .onPreferenceChange(SnapshotPerceptualPrecisionPreferenceKey.self) { perceptualPrecision = $0 } + + let matchingView = isScreen ? AnyView(view) : AnyView(view + .frame(width: device.size?.width) + .fixedSize(horizontal: false, vertical: true) + ) + + return withSnapshotTesting(record: recordMode) { + verifySnapshot(of: matchingView, + as: .prefireImage(precision: { precision }, + perceptualPrecision: { perceptualPrecision }, + duration: { delay }, + layout: isScreen ? .device(config: device) : .sizeThatFits, + traits: traits), + named: name, + testName: testName) + } + } +} + +// MARK: - SnapshotTesting + Extensions + +private extension PreviewDevice { + func snapshotDevice() -> ViewImageConfig? { + switch rawValue { + case "iPhone 16", "iPhone 15", "iPhone 14", "iPhone 13", "iPhone 12", "iPhone 11", "iPhone 10": + return .iPhoneX + case "iPhone 6", "iPhone 6s", "iPhone 7", "iPhone 8": + return .iPhone8 + case "iPhone 6 Plus", "iPhone 6s Plus", "iPhone 8 Plus": + return .iPhone8Plus + case "iPhone SE (1st generation)", "iPhone SE (2nd generation)": + return .iPhoneSe + case "iPad": + return .iPad10_2 + case "iPad Mini": + return .iPadMini + case "iPad Pro 11": + return .iPadPro11 + case "iPad Pro 12.9": + return .iPadPro12_9 + default: return nil + } + } +} + +private extension Snapshotting where Value: SwiftUI.View, Format == UIImage { + static func prefireImage(drawHierarchyInKeyWindow: Bool = false, + precision: @escaping () -> Float, + perceptualPrecision: @escaping () -> Float, + duration: @escaping () -> TimeInterval, + layout: SwiftUISnapshotLayout = .sizeThatFits, + traits: UITraitCollection = .init()) -> Snapshotting { + let config: ViewImageConfig + + switch layout { + #if os(iOS) || os(tvOS) + case let .device(config: deviceConfig): + config = deviceConfig + #endif + case .sizeThatFits: + // Make sure to use the workaround safe area insets. + config = .init(safeArea: .one, size: nil, traits: traits) + case let .fixed(width: width, height: height): + let size = CGSize(width: width, height: height) + // Make sure to use the workaround safe area insets. + config = .init(safeArea: .one, size: size, traits: traits) + } + + return SimplySnapshotting(pathExtension: "png", diffing: .prefireImage(precision: precision, perceptualPrecision: perceptualPrecision, scale: traits.displayScale)) + .asyncPullback { view in + var config = config + + let controller: UIViewController + + if config.size != nil { + controller = UIHostingController(rootView: view) + } else { + let hostingController = UIHostingController(rootView: view) + + let maxSize = CGSize.zero + config.size = hostingController.sizeThatFits(in: maxSize) + + controller = hostingController + } + + return Async { callback in + let strategy = snapshotView(config: config, + drawHierarchyInKeyWindow: drawHierarchyInKeyWindow, + traits: traits, + view: controller.view, + viewController: controller) + + let duration = duration() + if duration != .zero { + let expectation = XCTestExpectation(description: "Wait") + DispatchQueue.main.asyncAfter(deadline: .now() + duration) { + expectation.fulfill() + } + _ = XCTWaiter.wait(for: [expectation], timeout: duration + 1) + } + strategy.run(callback) + } + } + } +} + +private extension Diffing where Value == UIImage { + static func prefireImage(precision: @escaping () -> Float, perceptualPrecision: @escaping () -> Float, scale: CGFloat?) -> Diffing { + lazy var originalDiffing = Diffing.image(precision: precision(), perceptualPrecision: 0.98, scale: scale) + return Diffing(toData: { originalDiffing.toData($0) }, + fromData: { originalDiffing.fromData($0) }, + diff: { originalDiffing.diff($0, $1) }) + } +} + +private extension UIEdgeInsets { + /// A custom inset that prevents the snapshotting library from rendering the + /// origin at (10000, 10000) which breaks some of our views such as MessageText. + static var one: UIEdgeInsets { UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1) } +} diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPad-en-GB.1.png new file mode 100644 index 0000000000..c6d1158f0a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:484136606f2b3dd8cdc29f5b4f943622c2e770672c5a1980ff0e7db55a499c09 +size 114860 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..2ffab2fc07 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bdfd7ebbf5f14f045bdaf416aa405d277edce74fdd3f7040f82b488e60074dc1 +size 126470 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..2dfdb18eb5 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:987c192f5c1ab4c07fc198c190b3867843d9b459e6edf71a5057102853fe9941 +size 66997 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..e1f4810213 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd509058af6af0c07b4350bf19e33dc16ca76c977be0c99d03614f4810374235 +size 84485 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPhone-16-pseudo.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPad-en-GB.1.png new file mode 100644 index 0000000000..bca1ba570f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4959f2b957a1fc21cd35b690b5eea1fc9aab9cc84fe13c3a50b3fbecea276e3c +size 110926 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPad-pseudo.1.png new file mode 100644 index 0000000000..9547089cfb --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4f3d9c02c0c19490c9b1245d86dfdd97468f0cafa8c32bb9d01a62c1dccca6a9 +size 118558 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..a13dfe7638 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7558f09b10e62a9a111e91fe259f86c3709bf354867b406b23a3a122c67d9d29 +size 73551 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..d4d76a69c9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2bea6d31ae7c93fb10936d2af89bdefa799d2a8d5a314c2d7e351dd817c6bf68 +size 87505 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_analyticsSettingsScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsSettingsScreen-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_analyticsSettingsScreen-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsSettingsScreen-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_analyticsSettingsScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsSettingsScreen-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_analyticsSettingsScreen-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsSettingsScreen-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_analyticsSettingsScreen-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsSettingsScreen-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_analyticsSettingsScreen-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsSettingsScreen-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_analyticsSettingsScreen-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsSettingsScreen-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_analyticsSettingsScreen-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_analyticsSettingsScreen-iPhone-16-pseudo.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockScreen-iPad-en-GB.1.png new file mode 100644 index 0000000000..c9a030cde9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:56c1d96bd433043bd76ec90173c6e0a4d8acab8f07425e59f49973e203bf7d59 +size 116471 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..3142de04d9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:87b876922756638f6dcecab250fb88d902c7fbb812d8ad13c2985a37d6312287 +size 125129 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockScreen-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..478707bb96 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockScreen-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:86edb6ef21be16e30d1dcbfe0b97bad62777455f33fc0f482ea80df5cc27a2ad +size 70704 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockScreen-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..a1b36c5e5f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockScreen-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a48b16f920e15a66dde777206198e6cb1c5233606e3dd77dd12b56c716c4d64 +size 77691 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-en-GB.Face-ID.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-en-GB.Face-ID.png new file mode 100644 index 0000000000..b8a1f097c7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-en-GB.Face-ID.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8148695b7f4dd66e4334d77d7212f37b833875c9f54ca14f4adcb2c524cce376 +size 100027 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-en-GB.Touch-ID.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-en-GB.Touch-ID.png new file mode 100644 index 0000000000..813078acb8 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-en-GB.Touch-ID.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67c24da2a7bf190fa6be71deb109c940937d3757d9a7d98d4f08c77d9559b628 +size 108753 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-pseudo.Face-ID.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-pseudo.Face-ID.png new file mode 100644 index 0000000000..e7ee4182cf --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-pseudo.Face-ID.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b87b6ae78579356c33573d880c4756dd8c47a850567275590ce4e12caf855b35 +size 113618 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-pseudo.Touch-ID.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-pseudo.Touch-ID.png new file mode 100644 index 0000000000..3c777c6816 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-pseudo.Touch-ID.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:de1cae3b1f9bf38a1bfb2580707eab8bf290daf0502e7e2026af14c8f2c75e3a +size 122216 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPhone-16-en-GB.Face-ID.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPhone-16-en-GB.Face-ID.png new file mode 100644 index 0000000000..b674268197 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPhone-16-en-GB.Face-ID.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb7d1a41531c3f361c5d3fc5e5e518123131ad15431deb258c00276989e9e78e +size 57266 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPhone-15-en-GB.Touch-ID.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPhone-16-en-GB.Touch-ID.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPhone-15-en-GB.Touch-ID.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPhone-16-en-GB.Touch-ID.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPhone-16-pseudo.Face-ID.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPhone-16-pseudo.Face-ID.png new file mode 100644 index 0000000000..313647dfea --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPhone-16-pseudo.Face-ID.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f472a38eb8971e54a1ee3df632082f817d074b607c5836394259a3b14d084052 +size 73270 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPhone-15-pseudo.Touch-ID.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPhone-16-pseudo.Touch-ID.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPhone-15-pseudo.Touch-ID.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPhone-16-pseudo.Touch-ID.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Confirm.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Confirm.png new file mode 100644 index 0000000000..57a11fe679 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Confirm.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e8e2c0d5fb539547eb17874010dc890a90283cd99a9baf63a91b8b4d4bccfc1 +size 102419 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Create.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Create.png new file mode 100644 index 0000000000..3aef94e6e5 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Create.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a1da726841138e630d6e85133cda1fd90baab69fbaf6513c465d4e56ead739e7 +size 102732 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Unlock-Failed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Unlock-Failed.png new file mode 100644 index 0000000000..e4e1bfcdce --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Unlock-Failed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:13118c3e920fdee262b388f2ed710f631c06502ef2447074c9c8551e2939a8ff +size 92803 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Unlock.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Unlock.png new file mode 100644 index 0000000000..c1138af9bb --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Unlock.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c25a877355d3256f14e6029a877bdf86cff7b792b7639e33acb50fa09de34987 +size 91322 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Confirm.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Confirm.png new file mode 100644 index 0000000000..e6cc07ef3b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Confirm.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c96e282d280d870f4e5f625381034ae37572fd3f84a88314ae2ca1d265d4fb28 +size 120848 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Create.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Create.png new file mode 100644 index 0000000000..294a4f6a23 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Create.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:268ba715124976362a3bffb717681af0d82b8e93562d2374a70ff2bf4cde752f +size 121144 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Unlock-Failed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Unlock-Failed.png new file mode 100644 index 0000000000..34c82523dd --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Unlock-Failed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a7afee97b88a11735eaf6a7feebc86b16d48bf9c07e5a4842d05223f542d0b0d +size 94251 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Unlock.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Unlock.png new file mode 100644 index 0000000000..49eaaa08d6 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Unlock.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:82e57447f74abc770a97c13e2c68cff73c02aa46321596d620195a18de078691 +size 93896 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-15-en-GB.Confirm.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-16-en-GB.Confirm.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-15-en-GB.Confirm.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-16-en-GB.Confirm.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-15-en-GB.Create.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-16-en-GB.Create.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-15-en-GB.Create.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-16-en-GB.Create.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-15-en-GB.Unlock-Failed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-16-en-GB.Unlock-Failed.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-15-en-GB.Unlock-Failed.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-16-en-GB.Unlock-Failed.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-15-en-GB.Unlock.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-16-en-GB.Unlock.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-15-en-GB.Unlock.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-16-en-GB.Unlock.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-15-pseudo.Confirm.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-16-pseudo.Confirm.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-15-pseudo.Confirm.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-16-pseudo.Confirm.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-15-pseudo.Create.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-16-pseudo.Create.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-15-pseudo.Create.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-16-pseudo.Create.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-15-pseudo.Unlock-Failed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-16-pseudo.Unlock-Failed.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-15-pseudo.Unlock-Failed.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-16-pseudo.Unlock-Failed.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-15-pseudo.Unlock.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-16-pseudo.Unlock.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-15-pseudo.Unlock.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPhone-16-pseudo.Unlock.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-en-GB.Face-ID.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-en-GB.Face-ID.png new file mode 100644 index 0000000000..148a893db9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-en-GB.Face-ID.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:356f1a6731607c3e97173d8ce06c68b83ad4cca3e15357eb44c1ce7037ddafcf +size 97611 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-en-GB.PIN-only.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-en-GB.PIN-only.png new file mode 100644 index 0000000000..28914580e9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-en-GB.PIN-only.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:727f3dc6aabbeb986ea755b0595a0f8a7eaee848d15fd95eb2d21ba563432ffa +size 89618 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-en-GB.Touch-ID-Mandatory.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-en-GB.Touch-ID-Mandatory.png new file mode 100644 index 0000000000..786646c956 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-en-GB.Touch-ID-Mandatory.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7a7d7afe33653c06fed0f88765f7a8ddd45236df784c18cf210161eb3ee0624c +size 93321 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-pseudo.Face-ID.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-pseudo.Face-ID.png new file mode 100644 index 0000000000..bb2f853422 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-pseudo.Face-ID.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc0e088784cef05e8bfe6c997facbcaff0c55021109f29225933aec28f7a7273 +size 102032 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-pseudo.PIN-only.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-pseudo.PIN-only.png new file mode 100644 index 0000000000..2f16ad8a23 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-pseudo.PIN-only.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b23850550a44b8c4ff89abb3fcaeb7133bf1d0257723c850547d76b5e943aa25 +size 91563 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-pseudo.Touch-ID-Mandatory.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-pseudo.Touch-ID-Mandatory.png new file mode 100644 index 0000000000..adfbdb4b01 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-pseudo.Touch-ID-Mandatory.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:908b9f86a6cb31e620009f7bff398ead7d68241eedc5f8e59fe01d39e5cf167d +size 97588 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-16-en-GB.Face-ID.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-16-en-GB.Face-ID.png new file mode 100644 index 0000000000..4ba916e570 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-16-en-GB.Face-ID.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b7a4a6ca895b8d71d079176ab44732316aa7149992b21ab768be82a6e7dbc4ea +size 49095 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-16-en-GB.PIN-only.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-16-en-GB.PIN-only.png new file mode 100644 index 0000000000..6f71f50a89 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-16-en-GB.PIN-only.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:41acc3cd4775ba06b537fedad75903356275269b02a8c80c56cfa8e8b9411a44 +size 42396 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-16-en-GB.Touch-ID-Mandatory.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-16-en-GB.Touch-ID-Mandatory.png new file mode 100644 index 0000000000..dae7d2c3cb --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-16-en-GB.Touch-ID-Mandatory.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f8942f3d67c62661dbebc6580c3d79853ab49673f846ca481d4740153d04625c +size 45702 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-16-pseudo.Face-ID.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-16-pseudo.Face-ID.png new file mode 100644 index 0000000000..0fc89a12c0 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-16-pseudo.Face-ID.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e8e967bf9f379fa62f6ca21a70e0af0bb146a0ac78a7a2eea0a97c11e6a10afd +size 56649 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-16-pseudo.PIN-only.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-16-pseudo.PIN-only.png new file mode 100644 index 0000000000..10ca3e959c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-16-pseudo.PIN-only.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d12573998b27fb7094012b265f02558a6ec1d47282daedda183ec64e7abb190c +size 46489 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-16-pseudo.Touch-ID-Mandatory.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-16-pseudo.Touch-ID-Mandatory.png new file mode 100644 index 0000000000..011db1cf48 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-16-pseudo.Touch-ID-Mandatory.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8c9ae6aec2e39d2782be188c197e97e0a5c617a67adbc6f5cfd0ee6866e7eed5 +size 52118 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPad-en-GB.1.png new file mode 100644 index 0000000000..6f16e67502 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9739d20915112a358519b0ad80382b27827df4b26dd504a08d71ebe3ec041ff3 +size 112019 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..fc6c4557d8 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d5727c77119c15ced3ed6e082ce49f62700182108d9e1180aec189eb263faa50 +size 131397 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..7317433110 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b4bfbf0ff45d25c9f6925fe2669444bcdb6a3552c8c4d92855e47bf99bb181fd +size 511521 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..88a7cc505a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6e044f8265712ff0ebe207d32eedc5f9ff93ede67e398ea5fa9bb5339624584a +size 535038 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.DM.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.DM.png new file mode 100644 index 0000000000..97156a01fe --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.DM.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef2a54b62e2f537e2bd2b430cc899cd0928bf4e825e76bfcc42d96186daa5026 +size 123993 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.Members.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.Members.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.Members.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.Members.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.Room.png new file mode 100644 index 0000000000..0e0ca7e0e3 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.Room.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d2557dc6f6c8bf357f8941d5e34eca1bad97930e73ffcb65e747f43edab5ee9 +size 142395 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.DM.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.DM.png new file mode 100644 index 0000000000..634671c64a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.DM.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:85de72de76d8bdc38d38ebbc0cf9f3cb696aef6b9567e9ee998886601aedc34a +size 124368 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.Members.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.Members.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.Members.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.Members.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.Room.png new file mode 100644 index 0000000000..541513992d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.Room.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b9ace9ee3ae23e2212560269db976c2667f4e7024c8318cb744770ebf1453242 +size 143790 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-en-GB.DM.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-en-GB.DM.png new file mode 100644 index 0000000000..6c9ee54b88 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-en-GB.DM.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8d554256c0bed2b0dec2ab2357fb0b6f44e5f927e8766f5134d0083ebf8b77d6 +size 72733 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-15-en-GB.Members.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-en-GB.Members.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-15-en-GB.Members.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-en-GB.Members.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-en-GB.Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-en-GB.Room.png new file mode 100644 index 0000000000..0b31a5e511 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-en-GB.Room.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:781c7c0aa241138c17c18ca152815a0476fb9722c174f24dff3afffcea9cb2d5 +size 86998 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-pseudo.DM.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-pseudo.DM.png new file mode 100644 index 0000000000..8386a8730d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-pseudo.DM.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:805b359ab4c8880717b6771e0acc049b7a8eed27214d4ef1833183d349e7dfa7 +size 74400 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-15-pseudo.Members.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-pseudo.Members.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-15-pseudo.Members.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-pseudo.Members.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-pseudo.Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-pseudo.Room.png new file mode 100644 index 0000000000..86d56f78f4 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-pseudo.Room.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dbb2e14c8bf7b0a9b5082db07e123732ac26ef431418e6d3d62011a2100a7e7e +size 91331 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_badgeLabel-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_badgeLabel-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_badgeLabel-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_badgeLabel-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_badgeLabel-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_badgeLabel-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_badgeLabel-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_badgeLabel-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_badgeLabel-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_badgeLabel-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_badgeLabel-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_badgeLabel-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_badgeLabel-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_badgeLabel-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_badgeLabel-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_badgeLabel-iPhone-16-pseudo.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPad-en-GB.1.png new file mode 100644 index 0000000000..2ad01e2762 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a610051a00b4fd05222226332611b131f8fc5e9658fa637d87e1bc2c93f1d077 +size 134219 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..36cbdfd9da --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e32cef689f4965a86619052939adc033bb752ac52e5941e51c6d9381fd6a4e0b +size 134827 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..02daaed432 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:56034d6fdb06f469ebbb3328591e2106428d8f1e6cd52539ff3a5545ea65957c +size 81251 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..ce1dc853be --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9e2a1d28a41ed0bc2e42b4f3a6ac7fedc641052847cc5d8694b30131a742399e +size 81848 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 new file mode 100644 index 0000000000..b828a03bc4 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a630df63ebb09adbc2a582c467c245664bb590e3da2ccee4543522cb4222c384 +size 156374 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 new file mode 100644 index 0000000000..fb5ea2c6a4 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-en-GB.2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:388c30b2d7eb90e90331c5c05b3a7850c073bc27f6c7978fa306cb320cda6b38 +size 205646 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-pseudo.1.png new file mode 100644 index 0000000000..73d3529729 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9b94e9e5b8929235c3dc577b61cce527d95b0f499760a55b9e48b9451d100fa9 +size 195199 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-pseudo.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-pseudo.2.png new file mode 100644 index 0000000000..42b009a8de --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-pseudo.2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:261467174d0e96432d963ca4a9924dc0ecabef796670410bacf6d30c60028229 +size 241882 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 new file mode 100644 index 0000000000..b40a04a39c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b4ca48111eef3faa437cab02d2f9b77f7ea0e0db7044ce356c242ae03da51719 +size 112787 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 new file mode 100644 index 0000000000..eb98ce3b89 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-en-GB.2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:119511075ab801b223b83f1101c2fb3da1c9ab11dcee8d193b668b46ee52cb4f +size 157198 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 new file mode 100644 index 0000000000..f7c6a26c2c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e898c781a857620e338ab3a84ece132c831a4b19351ee5f70109d4e137bf71a7 +size 166289 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 new file mode 100644 index 0000000000..7cbcb5a18d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-pseudo.2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9734dd90fa64366676961ca677e8d176ad36ba308f9e6939a209368a117f2d70 +size 192993 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_collapsibleRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_collapsibleRoomTimelineView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_collapsibleRoomTimelineView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_collapsibleRoomTimelineView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_collapsibleRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_collapsibleRoomTimelineView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_collapsibleRoomTimelineView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_collapsibleRoomTimelineView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_collapsibleRoomTimelineView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_collapsibleRoomTimelineView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_collapsibleRoomTimelineView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_collapsibleRoomTimelineView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_collapsibleRoomTimelineView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_collapsibleRoomTimelineView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_collapsibleRoomTimelineView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_collapsibleRoomTimelineView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-en-GB.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-en-GB.2.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-en-GB.2.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-en-GB.2.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-pseudo.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-pseudo.2.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-pseudo.2.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-pseudo.2.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-15-en-GB.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-16-en-GB.2.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-15-en-GB.2.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-16-en-GB.2.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-15-pseudo.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-16-pseudo.2.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-15-pseudo.2.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-16-pseudo.2.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Reply.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Reply.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Reply.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Reply.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Voice-Message.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Voice-Message.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Voice-Message.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Voice-Message.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.With-Suggestions.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.With-Suggestions.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.With-Suggestions.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.With-Suggestions.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Reply.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Reply.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Reply.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Reply.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Voice-Message.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Voice-Message.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Voice-Message.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Voice-Message.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.With-Suggestions.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.With-Suggestions.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.With-Suggestions.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.With-Suggestions.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-15-en-GB.Reply.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.Reply.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-15-en-GB.Reply.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.Reply.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-15-en-GB.Voice-Message.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.Voice-Message.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-15-en-GB.Voice-Message.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.Voice-Message.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-15-en-GB.With-Suggestions.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.With-Suggestions.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-15-en-GB.With-Suggestions.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.With-Suggestions.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-15-pseudo.Reply.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.Reply.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-15-pseudo.Reply.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.Reply.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-15-pseudo.Voice-Message.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.Voice-Message.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-15-pseudo.Voice-Message.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.Voice-Message.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-15-pseudo.With-Suggestions.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.With-Suggestions.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-15-pseudo.With-Suggestions.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.With-Suggestions.png 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 new file mode 100644 index 0000000000..040f987ee0 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room-without-users.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d4472c871f2188a6d276ed4ef82e48b8a135afcc60ec83cbd974dfe98a8b332d +size 147686 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 new file mode 100644 index 0000000000..d7c08ebcf4 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a4c6a7b0eddf99d68deee0202bfbe20d97e8bcd7c2560feb592954db198ee99 +size 147377 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 new file mode 100644 index 0000000000..57c4ed90e8 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room-without-users.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a3bfa52c8580af52c0aa96a65cbe848f88ed7232b0a29270b2d7ebc2c769b35a +size 171707 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 new file mode 100644 index 0000000000..180cc761cf --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b38d6fd62142d45fd83313d5a7af2954bd0b339cb875f36d59cf0e5f0fbb22cb +size 173026 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 new file mode 100644 index 0000000000..c93ed1d395 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room-without-users.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:effcd533de2760ac2def29097a09147cf7d60fa2bd8844088c123dcce9e641a8 +size 99367 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 new file mode 100644 index 0000000000..91834a38f6 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:248815b3152639d27193e7ab2c412c76036ab6d0394c3b89cc827a4bf4634885 +size 100098 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 new file mode 100644 index 0000000000..a8f7b5af29 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room-without-users.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f14434bda971e011a023d6cfcba900be70ee07d583100a9db3bcc5c827cd6b2a +size 138818 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 new file mode 100644 index 0000000000..442b2051c7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6908ceac42a93152b2dfe3c4d2781f4f5cb96bfb165bf6896283cc529cd81e03 +size 139491 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 new file mode 100644 index 0000000000..b0c7cf957a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eb884b89ca3e8cbcc7db88df0fa167e83548ea66a56b60afab6ef21b669e76db +size 169987 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..313b7ce595 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0258e979e9ecabb3632bfdec3f4b6a5f599ca37a9a6a465af6d2e5a8680f50d7 +size 219349 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 new file mode 100644 index 0000000000..2b79870842 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0f84fd74f90a963fda1925746366c51b3db2226499bb2d0e3eb84841f20bc399 +size 121896 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 new file mode 100644 index 0000000000..677ea9520c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18f70a5032d165efc76a409665a2a25ada0b4a69874b394485b0623d672146f7 +size 190128 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 new file mode 100644 index 0000000000..58df3e323f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPad-en-GB.Screen.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d0792296479dd1e54348bd980f10469dd8b1409cc0a02e2ae3fcbf349a019482 +size 984410 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPad-pseudo.Screen.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPad-pseudo.Screen.png new file mode 100644 index 0000000000..5989d9b67d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPad-pseudo.Screen.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8023ece990f28365497bd0fea7a1285e0cc70720bc717271051fc68f8c8588b0 +size 987899 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 new file mode 100644 index 0000000000..670299a350 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPhone-16-en-GB.Screen.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3181bdcf7d91c89da8af03b325c9ca5880c3e0a97c67bfb74da7c0c22048b19 +size 36664 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 new file mode 100644 index 0000000000..35e93f0c2b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPhone-16-pseudo.Screen.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0320762f030bc3ceddd164fb0fff5ad4743bbf2667039921a15a59bb2366b0a5 +size 38589 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_emojiPickerScreenHeaderView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreenHeaderView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_emojiPickerScreenHeaderView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreenHeaderView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_emojiPickerScreenHeaderView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreenHeaderView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_emojiPickerScreenHeaderView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreenHeaderView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_emojiPickerScreenHeaderView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreenHeaderView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_emojiPickerScreenHeaderView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreenHeaderView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_emojiPickerScreenHeaderView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreenHeaderView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_emojiPickerScreenHeaderView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreenHeaderView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPad-en-GB.1.png new file mode 100644 index 0000000000..1b7ee2757d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e43762e16cf7619be64aff1f0510ce618fb6980248df235bbcf4d017d9e94f14 +size 100528 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..55cd644bf6 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:86d58428192333e6aa8697a1e22c115bbbea4183e29100e4e75ea6fc1c377c4c +size 117766 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..999facff08 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a83ab0654a14096806604c8ba2beb2e762651799283b0313af34030634d2c025 +size 56895 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..6e2b095584 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:af2422461ff5afc9dcd3f26a6cda3801ea64c163644f4a02bef28ac5fe2363c7 +size 73087 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPad-en-GB.1.png new file mode 100644 index 0000000000..5d8e2096cc --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1abe1380fff11977438738ea9e184efe8a6c2d3a4a4eab0b89caef7d5384cf14 +size 153800 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..8791a6dc30 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:04be415de88b73c1cf1757bdad7f8e7ab5b366b2c669fc9af00e5dd0fde7c519 +size 206442 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..e967ef99ee --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c158d6914bbd77b6a473a3042ad9f7ca5be135afc83277542962532311b77023 +size 104899 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..6a82c27e1a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c6738f263f313d058b3af80f5d6dd6b752500fe56e3650eda820ebcfb183798a +size 157963 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_estimatedWaveformView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_estimatedWaveformView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_estimatedWaveformView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_estimatedWaveformView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_estimatedWaveformView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_estimatedWaveformView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_estimatedWaveformView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_estimatedWaveformView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_estimatedWaveformView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_estimatedWaveformView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_estimatedWaveformView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_estimatedWaveformView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_estimatedWaveformView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_estimatedWaveformView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_estimatedWaveformView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_estimatedWaveformView-iPhone-16-pseudo.1.png 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 new file mode 100644 index 0000000000..2bcba76ae0 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4f624a30e09d9565a05f87d05ccf04078398f143b7932dac46667be81cb3e62b +size 97559 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPad-pseudo.1.png new file mode 100644 index 0000000000..2bcba76ae0 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4f624a30e09d9565a05f87d05ccf04078398f143b7932dac46667be81cb3e62b +size 97559 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 new file mode 100644 index 0000000000..83d78ac8e7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1aa13a458240d535e549c8807310618cefa9d668e77fb0e7e961c247f1f16cd3 +size 55007 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 new file mode 100644 index 0000000000..83d78ac8e7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1aa13a458240d535e549c8807310618cefa9d668e77fb0e7e961c247f1f16cd3 +size 55007 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_formButtonStyles-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formButtonStyles-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_formButtonStyles-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_formButtonStyles-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_formButtonStyles-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formButtonStyles-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_formButtonStyles-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_formButtonStyles-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_formButtonStyles-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formButtonStyles-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_formButtonStyles-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_formButtonStyles-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_formButtonStyles-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formButtonStyles-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_formButtonStyles-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_formButtonStyles-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_formattedBodyText-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_formattedBodyText-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_formattedBodyText-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_formattedBodyText-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_formattedBodyText-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_formattedBodyText-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_formattedBodyText-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_formattedBodyText-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_formattingToolbar-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattingToolbar-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_formattingToolbar-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattingToolbar-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_formattingToolbar-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattingToolbar-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_formattingToolbar-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattingToolbar-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_formattingToolbar-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattingToolbar-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_formattingToolbar-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattingToolbar-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_formattingToolbar-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattingToolbar-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_formattingToolbar-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattingToolbar-iPhone-16-pseudo.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-en-GB.Bloom.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-en-GB.Bloom.png new file mode 100644 index 0000000000..311bf2178a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-en-GB.Bloom.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:673ae32a0c035cbe1e6da82e5140dc8a8420809162191c184469d7740eadb78e +size 1920581 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-en-GB.Gradient.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-en-GB.Gradient.png new file mode 100644 index 0000000000..53491fc148 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-en-GB.Gradient.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dcaad3ff74d7df481f22d5a72a6fd57997023ed8b92df7fbc40bf965bf01001f +size 548528 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-en-GB.Plain.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-en-GB.Plain.png new file mode 100644 index 0000000000..8c2fe5908c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-en-GB.Plain.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8311e36f8f112744e63a3f70650eccefc992f877d694a8e910ab056113a6e756 +size 118243 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-pseudo.Bloom.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-pseudo.Bloom.png new file mode 100644 index 0000000000..784899d4e2 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-pseudo.Bloom.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:141ac92b6df2462b2c6c9a4fd79c43e8e93b20ce6258e4c29d042bd0b7cff0a1 +size 1940834 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-pseudo.Gradient.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-pseudo.Gradient.png new file mode 100644 index 0000000000..763aabdc8f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-pseudo.Gradient.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:46f6df56683db5ad4bf535d17f7b007718aa1c2ba1874ac905375a983e4330b1 +size 567359 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-pseudo.Plain.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-pseudo.Plain.png new file mode 100644 index 0000000000..95e79d1543 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-pseudo.Plain.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cfb0be95a15460ea4e48d4244a37a02af3198061ccb39b49f6742d3469e14f14 +size 124562 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-16-en-GB.Bloom.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-16-en-GB.Bloom.png new file mode 100644 index 0000000000..c6762375b4 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-16-en-GB.Bloom.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79a9b654dce63490f300e49dc1b555858ad1998f615572fb90df7743bfd39f65 +size 779384 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-16-en-GB.Gradient.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-16-en-GB.Gradient.png new file mode 100644 index 0000000000..62fe7f1a9b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-16-en-GB.Gradient.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4c817de082a78386f62d715bc2a02d0771337713d1dd903c8f509230c4baed43 +size 347661 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-16-en-GB.Plain.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-16-en-GB.Plain.png new file mode 100644 index 0000000000..476d5bc725 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-16-en-GB.Plain.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:880f5d0cacc0a2f72503b8e60857eb82087817c7968774a50b8ada237daef804 +size 72343 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-16-pseudo.Bloom.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-16-pseudo.Bloom.png new file mode 100644 index 0000000000..1d145a59c7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-16-pseudo.Bloom.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa13af20da0e71c18721b1391c7bf114b7fb7b9bff5436b8ea300b406a6cdb1d +size 802263 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-16-pseudo.Gradient.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-16-pseudo.Gradient.png new file mode 100644 index 0000000000..29cab0b899 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-16-pseudo.Gradient.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:82c0496f3e25574aba0f765d36153695473217674587e21586ea3ce3219f9ad7 +size 367570 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-16-pseudo.Plain.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-16-pseudo.Plain.png new file mode 100644 index 0000000000..8a2a999b1c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-16-pseudo.Plain.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:31cccf2a31654defb6d13929f10ec3311fa1478fd00f0842493f686e02434a7c +size 88823 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 new file mode 100644 index 0000000000..784d368a36 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:481969f82410ed28b3c259d53e88310fd5669d1c6041020c99c47a7a64fde666 +size 151180 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..fb1a5abde9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac9dc777f9bdaca948c7a5cf56aebb163ff80be491a124c78084b5d1309396af +size 151589 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_globalSearchScreen-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_globalSearchScreen-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_globalSearchScreen-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_globalSearchScreen-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPhone-16-pseudo.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_heroImage-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_heroImage-iPad-en-GB.1.png new file mode 100644 index 0000000000..8a22529d51 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_heroImage-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:798f00aea1c63551ad62f6f926fac78bf6a52b051a84700205f8013b121c8c5d +size 86845 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_heroImage-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_heroImage-iPad-pseudo.1.png new file mode 100644 index 0000000000..8a22529d51 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_heroImage-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:798f00aea1c63551ad62f6f926fac78bf6a52b051a84700205f8013b121c8c5d +size 86845 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_heroImage-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_heroImage-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..74cb603767 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_heroImage-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:df39d35a4bc393f96bec96b9741cb1719faad3f39108e4efc74ddbd542a01b6f +size 45643 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_heroImage-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_heroImage-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..74cb603767 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_heroImage-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:df39d35a4bc393f96bec96b9741cb1719faad3f39108e4efc74ddbd542a01b6f +size 45643 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPad-en-GB.Layout.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPad-en-GB.Layout.png new file mode 100644 index 0000000000..a371795b57 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPad-en-GB.Layout.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3137ef502a6372a6da696f5b0d304267936bc10a708812e09e2791f9965369df +size 277163 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPad-pseudo.Layout.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPad-pseudo.Layout.png new file mode 100644 index 0000000000..a371795b57 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPad-pseudo.Layout.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3137ef502a6372a6da696f5b0d304267936bc10a708812e09e2791f9965369df +size 277163 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPhone-16-en-GB.Layout.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPhone-16-en-GB.Layout.png new file mode 100644 index 0000000000..528273a73c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPhone-16-en-GB.Layout.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:03acd358adcbe1b8186305336e16c036ed12ca313e6374996e5fdefd3be80ca4 +size 243464 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPhone-16-pseudo.Layout.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPhone-16-pseudo.Layout.png new file mode 100644 index 0000000000..528273a73c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPhone-16-pseudo.Layout.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:03acd358adcbe1b8186305336e16c036ed12ca313e6374996e5fdefd3be80ca4 +size 243464 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Empty.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Empty.png new file mode 100644 index 0000000000..c489696ec2 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Empty.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a9625fad4ed5ef0e9e84e46cc4e030d1a458d69b51f4086f9cbaceb95ddd1ec5 +size 91709 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 new file mode 100644 index 0000000000..d3262ec39a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Loaded.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6446cbff232a333151b62687164c119345a6b59f9bfb4f9f6684df607d6e7063 +size 242207 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Loading.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Loading.png new file mode 100644 index 0000000000..43bc504b47 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Loading.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:47a99702b22eb7a34297a605c0a148acbd728c6055134118d55ad0fea521e4fe +size 92263 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Migrating.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Migrating.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Migrating.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Migrating.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Empty.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Empty.png new file mode 100644 index 0000000000..2966582c48 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Empty.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7a9fbbaacd071a3903cfd194072d6177aa466f6e0701007aaf13925aadfd22db +size 96020 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Loaded.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Loaded.png new file mode 100644 index 0000000000..3e869c730a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Loaded.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1ad49c6c1b92c9e7c474fd232ff063b38ba82b6ca7d9836ddf81221e06c00756 +size 245418 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Loading.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Loading.png new file mode 100644 index 0000000000..cd091cfb3b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Loading.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79634b4686349a426958f301e37662e6f16cca5a0920289d962f0d453f68008c +size 92979 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Migrating.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Migrating.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Migrating.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Migrating.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-en-GB.Empty.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-en-GB.Empty.png new file mode 100644 index 0000000000..3fe0b247b1 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-en-GB.Empty.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6136573195a4b3389a9d06966e5f0e9a400d6ea247b2ff5210dcb0e139a957b5 +size 51143 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 new file mode 100644 index 0000000000..8fb9ed0f80 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-en-GB.Loaded.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fca553c7fbb54deea774d261146a597ea426e00529a7a7cd7d64efabd8b7a1e6 +size 178424 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-en-GB.Loading.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-en-GB.Loading.png new file mode 100644 index 0000000000..09e163094c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-en-GB.Loading.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe5b5125665231d85b57ab1d304c2c17d175caa696ee1f4dcd090438e1282472 +size 50384 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-en-GB.Migrating.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-en-GB.Migrating.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-en-GB.Migrating.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-en-GB.Migrating.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-pseudo.Empty.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-pseudo.Empty.png new file mode 100644 index 0000000000..7a3b62ec10 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-pseudo.Empty.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:42b66da0630c9f320e7e1dc1b19261c647c5758e21248f61df5f134fc41e6201 +size 51984 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 new file mode 100644 index 0000000000..d70680ecdb --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-pseudo.Loaded.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c595691dab7881f5dfc46a5051d23fdcf7fb9684c7f1fbe445829fff02b9bbdd +size 181004 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-pseudo.Loading.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-pseudo.Loading.png new file mode 100644 index 0000000000..c00a419605 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-pseudo.Loading.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ad1c396b788d81c14139d5a5a174baaaa85e350aee173255cc72e3242f5bf87 +size 51246 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-pseudo.Migrating.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-pseudo.Migrating.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-pseudo.Migrating.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-pseudo.Migrating.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-en-GB.Constrained-layout.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-en-GB.Constrained-layout.png new file mode 100644 index 0000000000..0e3b52958d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-en-GB.Constrained-layout.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ebfe8de438d992fe8f51f33bcc757b7b124242b8c752f58b703df377759b9c5 +size 131949 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-en-GB.Normal-Layout.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-en-GB.Normal-Layout.png new file mode 100644 index 0000000000..676bc23e4c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-en-GB.Normal-Layout.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:004961a95f94a2d910c175468250bc3eb5879dda0f08e8e98d4d99345dfc805a +size 100470 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-en-GB.View.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-en-GB.View.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-en-GB.View.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-en-GB.View.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-pseudo.Constrained-layout.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-pseudo.Constrained-layout.png new file mode 100644 index 0000000000..8f2a6897b1 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-pseudo.Constrained-layout.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da0ade7d5a64ebf42467efa00662a3f3a7ec8dbfa2f6d40710641b29f39e5f85 +size 147825 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-pseudo.Normal-Layout.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-pseudo.Normal-Layout.png new file mode 100644 index 0000000000..e7f1e4886e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-pseudo.Normal-Layout.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cad2edf4827ac3148449f461e91c167c1316e21ae6165dcf2b9e30b94aa43936 +size 107744 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-pseudo.View.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-pseudo.View.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-pseudo.View.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-pseudo.View.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-16-en-GB.Constrained-layout.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-16-en-GB.Constrained-layout.png new file mode 100644 index 0000000000..6173df5a9b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-16-en-GB.Constrained-layout.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:84a080dc610406b1c6396b9a401b453fa511a236ee917ed9e5f9bf9f5bd47267 +size 89041 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-16-en-GB.Normal-Layout.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-16-en-GB.Normal-Layout.png new file mode 100644 index 0000000000..a66a2dd902 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-16-en-GB.Normal-Layout.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:57e4333b991949aa51353efc807373474e74267387d5c9fd9e9d066fc78935b2 +size 59888 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-15-en-GB.View.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-16-en-GB.View.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-15-en-GB.View.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-16-en-GB.View.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-16-pseudo.Constrained-layout.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-16-pseudo.Constrained-layout.png new file mode 100644 index 0000000000..cc46dfe0f3 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-16-pseudo.Constrained-layout.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:04fa7f508a85d7f7549a3005ede9e42268dc9936f84b3e7676a2890bbc35a9b8 +size 131973 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-16-pseudo.Normal-Layout.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-16-pseudo.Normal-Layout.png new file mode 100644 index 0000000000..81d674a7fe --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-16-pseudo.Normal-Layout.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:154c41d09cb4447ace60c0e35429fe5fd069d78e97e7d34cb0615b2207641b44 +size 83632 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-15-pseudo.View.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-16-pseudo.View.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-15-pseudo.View.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-16-pseudo.View.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPhone-16-en-GB.1.png 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 new file mode 100644 index 0000000000..ced45925db --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:864a9495a46a2e9ad30cbb29dfbe3406ebaf388a196f016d6d36214897c1b69b +size 193428 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRecoveryKeyConfirmationBanner-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRecoveryKeyConfirmationBanner-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRecoveryKeyConfirmationBanner-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRecoveryKeyConfirmationBanner-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRecoveryKeyConfirmationBanner-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRecoveryKeyConfirmationBanner-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRecoveryKeyConfirmationBanner-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRecoveryKeyConfirmationBanner-iPad-pseudo.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRecoveryKeyConfirmationBanner-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRecoveryKeyConfirmationBanner-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..9128476ef8 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRecoveryKeyConfirmationBanner-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c788a03807032eac004c08138a80590a7cecf1c6a4d229a612fbfd9a2f8cf489 +size 58527 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRecoveryKeyConfirmationBanner-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRecoveryKeyConfirmationBanner-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..9c5c1a5eb9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRecoveryKeyConfirmationBanner-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b7284ecd8fd558b1ae9a746d27f690ef931bfccf4fb1308c2d7778ba3795a158 +size 79847 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-en-GB.Generic.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-en-GB.Generic.png new file mode 100644 index 0000000000..ff485cbf3c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-en-GB.Generic.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f2e64acc7685ad88338cdd6be6158c26c1f3e244f746240d331368026fd4a6a3 +size 220584 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-en-GB.Notifications-State.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-en-GB.Notifications-State.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-en-GB.Notifications-State.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-en-GB.Notifications-State.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-pseudo.Generic.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-pseudo.Generic.png new file mode 100644 index 0000000000..ff485cbf3c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-pseudo.Generic.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f2e64acc7685ad88338cdd6be6158c26c1f3e244f746240d331368026fd4a6a3 +size 220584 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-pseudo.Notifications-State.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-pseudo.Notifications-State.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-pseudo.Notifications-State.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-pseudo.Notifications-State.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-en-GB.Generic.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-en-GB.Generic.png new file mode 100644 index 0000000000..29dd6ede1f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-en-GB.Generic.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5603cf5b0486ea13e7044e07a7b9170a8651d1f995c4e225c0b3cc2c3a7b24ce +size 162192 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-15-en-GB.Notifications-State.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-en-GB.Notifications-State.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-15-en-GB.Notifications-State.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-en-GB.Notifications-State.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-pseudo.Generic.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-pseudo.Generic.png new file mode 100644 index 0000000000..29dd6ede1f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-pseudo.Generic.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5603cf5b0486ea13e7044e07a7b9170a8651d1f995c4e225c0b3cc2c3a7b24ce +size 162192 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-15-pseudo.Notifications-State.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-pseudo.Notifications-State.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-15-pseudo.Notifications-State.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-pseudo.Notifications-State.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenSlidingSyncMigrationBanner-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenSlidingSyncMigrationBanner-iPad-en-GB.1.png new file mode 100644 index 0000000000..090039dbd2 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenSlidingSyncMigrationBanner-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ed37c148a5a16aea018c2592948c53c4b3029f3fc6b7d618aa212192e7bc42e5 +size 108471 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenSlidingSyncMigrationBanner-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenSlidingSyncMigrationBanner-iPad-pseudo.1.png new file mode 100644 index 0000000000..a7607a8c65 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenSlidingSyncMigrationBanner-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18cce2502021c0927c3abbc975a24134257f23963a9197c7e6746d9745d34beb +size 130832 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenSlidingSyncMigrationBanner-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenSlidingSyncMigrationBanner-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..b872e23766 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenSlidingSyncMigrationBanner-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6abeb702cab50a0ef39cea1f34ebe5346692a5510f643415c2edfdac8a503bab +size 70709 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenSlidingSyncMigrationBanner-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenSlidingSyncMigrationBanner-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..195267b3f5 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenSlidingSyncMigrationBanner-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:edda50f8721edf0c8772896b4e1c6b855f5ca0e72c7363a887045e8e4742bfe2 +size 105929 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPad-en-GB.1.png new file mode 100644 index 0000000000..9168f11f5f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2914636f691599f5f379bc099e20e5727d1222479524c0a6b4ad670dd70daa05 +size 112687 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..08c759b75b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bae19c911103b9b2742a1f78fc0d63ba9e8b26cd35ea9e02263f2b51698a9b07 +size 125129 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..ba383dfaf5 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cfd45923268bc5e7755b17597290cf39451fa92abe4b514164d19fc21f934be5 +size 67005 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..f3434c808d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75c432bd34524fe3bc496b6b3306010bfdf4b51b00bcbd990286a01da8f5d9a0 +size 85907 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmedScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmedScreen-iPad-en-GB.1.png new file mode 100644 index 0000000000..ce8d89078f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmedScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:accd166f617c76fd93fb981e22091b0fa6fffb29800a2f9f9a52d97ee168070b +size 96564 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmedScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmedScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..269f0ceb99 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmedScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8bde634539569c48796d0edda577fe408b04ddfa4124268e4e37d5b45a13410c +size 109812 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmedScreen-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmedScreen-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmedScreen-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmedScreen-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmedScreen-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmedScreen-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmedScreen-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_identityConfirmedScreen-iPhone-16-pseudo.1.png 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 new file mode 100644 index 0000000000..5469ed0e38 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f63e72b33f82f8b679dd8b1fc810078438914d70d395c23abd13571d01643597 +size 227546 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPad-pseudo.1.png new file mode 100644 index 0000000000..5469ed0e38 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f63e72b33f82f8b679dd8b1fc810078438914d70d395c23abd13571d01643597 +size 227546 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 new file mode 100644 index 0000000000..bd08a52887 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb0bce1bf5571926c9ae760503e3aff11bfa962d646e257ab9481bc9496b95a6 +size 169079 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 new file mode 100644 index 0000000000..bd08a52887 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb0bce1bf5571926c9ae760503e3aff11bfa962d646e257ab9481bc9496b95a6 +size 169079 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 new file mode 100644 index 0000000000..658e8341f9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:137a69e36ec893a296f561ee7cfea1dea12150af45230333913f0a59a6d89a5b +size 86547 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..65f03ff89c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ee7e2090ff06b5594acd6df4410c8b160c7ede89cf630ad5b432caae39d33054 +size 89052 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 new file mode 100644 index 0000000000..39842c8146 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d2adccdf1a50ac993c1022959f955214ebd57c06d1a937b5ce24dade3a7c407e +size 41195 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 new file mode 100644 index 0000000000..872f01fd7c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5ac705453f81bd9dc87b8e446c9f7d0a88762015d6e30854b0c1ce106eff113a +size 43291 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPad-en-GB.1.png new file mode 100644 index 0000000000..1f01229504 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b5ecd6e793e32c8ec19cf7db4a430e7d3f33aa61c9c24fbc7bdd405cca34b33 +size 82049 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPad-pseudo.1.png new file mode 100644 index 0000000000..1f01229504 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b5ecd6e793e32c8ec19cf7db4a430e7d3f33aa61c9c24fbc7bdd405cca34b33 +size 82049 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..8db9bc1ba9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a04861f7a4af6e8dbb53995fa26e1c2ef07ee05b6e35241375879f1b1bc2ede3 +size 40855 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..8db9bc1ba9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a04861f7a4af6e8dbb53995fa26e1c2ef07ee05b6e35241375879f1b1bc2ede3 +size 40855 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 new file mode 100644 index 0000000000..e1d6fe4894 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Invite.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd4af69b4bbdbfa84069a1ea1ef0529292cf1404ddca978353b02fa9aafe4a22 +size 1982852 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 new file mode 100644 index 0000000000..7fc18921f5 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Join.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:146c20f80acac9bf9497aa93562cb930bea02e6fb82507d971a22c26bf3e28a6 +size 1946311 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 new file mode 100644 index 0000000000..1789652cdb --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knock.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b9bb89feeb7a80c3bdd110bf69eb2efb08b009ebcb30825a24c2343a537280df +size 1938161 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Unknown.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Unknown.png new file mode 100644 index 0000000000..f57487803d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Unknown.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:efda9145642c0bef47507f9de249565cb09897bfed8f4fa6ae79ec792c067fb5 +size 1890674 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invite.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invite.png new file mode 100644 index 0000000000..a19bcbcd62 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invite.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:21a35ce286f3b7b5001b84c2941f044483f2ca77b96d5c8367945658e732915d +size 1983924 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Join.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Join.png new file mode 100644 index 0000000000..d9ded5d4e5 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Join.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:48852e2e65d9c3000b2069521628f577426801ab4a804a1f30100540a573bc66 +size 1947292 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knock.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knock.png new file mode 100644 index 0000000000..60860bc7e2 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knock.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bd7969bf12e64467689fe589abd6f193425b114778f0cfac04ec6abf78000b98 +size 1938771 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Unknown.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Unknown.png new file mode 100644 index 0000000000..9b611d6ef7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Unknown.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b1e33030ab7373ae71f3ac6b2580a1187f8ec21d81da94831a3f8ea6fdbcfc0a +size 1895360 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 new file mode 100644 index 0000000000..c5acd00a66 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Invite.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bfcc6e059fd1bf8d93a5b1b4766030d1ade06cf0fb1ccdf887c3289c9649b358 +size 818216 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 new file mode 100644 index 0000000000..c1384ca8df --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Join.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eca394ab7064165321d8eba0c1110b56c5e815260cef52f69cc61ec7c4bc7d3b +size 796819 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 new file mode 100644 index 0000000000..49e1c4a792 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Knock.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4fb08acf5df0a46b166d2e0b4b4ebcdf399c5ce0acf6b6b728124b817aae8d0c +size 791872 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-en-GB.Unknown.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Unknown.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-en-GB.Unknown.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Unknown.png 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 new file mode 100644 index 0000000000..3f1c987835 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Invite.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6bebae9e971fb3e54e407e2b12ee145d60c1a1c72da97607feb75d2660194033 +size 820621 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 new file mode 100644 index 0000000000..0acd1dcc66 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Join.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7fb7955f605d2ad9e5678438af15a1a354baab5f00e59ca0ff458759e93d76b1 +size 798533 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 new file mode 100644 index 0000000000..c2b2930b16 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knock.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9685beb39e3ca4a7509b5438ec4733fce1019d8aae6fb12d2a1a87214a971b00 +size 793600 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-pseudo.Unknown.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Unknown.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-pseudo.Unknown.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Unknown.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_legalInformationScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_legalInformationScreen-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_legalInformationScreen-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_legalInformationScreen-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_legalInformationScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_legalInformationScreen-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_legalInformationScreen-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_legalInformationScreen-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_legalInformationScreen-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_legalInformationScreen-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_legalInformationScreen-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_legalInformationScreen-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_legalInformationScreen-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_legalInformationScreen-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_legalInformationScreen-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_legalInformationScreen-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_locationMarkerView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationMarkerView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_locationMarkerView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationMarkerView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_locationMarkerView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationMarkerView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_locationMarkerView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationMarkerView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_locationMarkerView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationMarkerView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_locationMarkerView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationMarkerView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_locationMarkerView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationMarkerView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_locationMarkerView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationMarkerView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPad-en-GB.Bubbles.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPad-en-GB.Bubbles.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPad-en-GB.Bubbles.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPad-en-GB.Bubbles.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPad-pseudo.Bubbles.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPad-pseudo.Bubbles.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPad-pseudo.Bubbles.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPad-pseudo.Bubbles.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPhone-15-en-GB.Bubbles.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPhone-16-en-GB.Bubbles.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPhone-15-en-GB.Bubbles.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPhone-16-en-GB.Bubbles.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPhone-15-pseudo.Bubbles.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPhone-16-pseudo.Bubbles.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPhone-15-pseudo.Bubbles.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPhone-16-pseudo.Bubbles.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.Credentials-Entered.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.Credentials-Entered.png new file mode 100644 index 0000000000..9ba7a98cd0 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.Credentials-Entered.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79822b8f61589c6f261eb71f0ab15c6a6bd2d9f386499c8bc6a2db22628ecbcf +size 95885 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.OIDC-Fallback.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.OIDC-Fallback.png new file mode 100644 index 0000000000..44e7172706 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.OIDC-Fallback.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3d59c0c3eee314426f46098f5c2341520eecfe59479cf1f6f79e967636b4b443 +size 99155 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.Unsupported.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.Unsupported.png new file mode 100644 index 0000000000..44e7172706 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.Unsupported.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3d59c0c3eee314426f46098f5c2341520eecfe59479cf1f6f79e967636b4b443 +size 99155 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 new file mode 100644 index 0000000000..44e7172706 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.matrix-org.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3d59c0c3eee314426f46098f5c2341520eecfe59479cf1f6f79e967636b4b443 +size 99155 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.Credentials-Entered.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.Credentials-Entered.png new file mode 100644 index 0000000000..f3f2e13880 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.Credentials-Entered.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:253ca4671f65641fabd2ada1a7789821585e1c3e0146e098f96dc4a90280f1d6 +size 101236 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.OIDC-Fallback.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.OIDC-Fallback.png new file mode 100644 index 0000000000..0084793ed8 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.OIDC-Fallback.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f40def8fbafb7262bb0fcbb806c75679ceb0c4912264e1dc912783bc5c627c21 +size 105228 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.Unsupported.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.Unsupported.png new file mode 100644 index 0000000000..0084793ed8 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.Unsupported.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f40def8fbafb7262bb0fcbb806c75679ceb0c4912264e1dc912783bc5c627c21 +size 105228 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 new file mode 100644 index 0000000000..0084793ed8 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.matrix-org.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f40def8fbafb7262bb0fcbb806c75679ceb0c4912264e1dc912783bc5c627c21 +size 105228 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPhone-15-en-GB.Credentials-Entered.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-en-GB.Credentials-Entered.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPhone-15-en-GB.Credentials-Entered.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-en-GB.Credentials-Entered.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPhone-15-en-GB.OIDC-Fallback.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-en-GB.OIDC-Fallback.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPhone-15-en-GB.OIDC-Fallback.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-en-GB.OIDC-Fallback.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPhone-15-en-GB.Unsupported.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-en-GB.Unsupported.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPhone-15-en-GB.Unsupported.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-en-GB.Unsupported.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPhone-15-en-GB.matrix-org.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-en-GB.matrix-org.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPhone-15-en-GB.matrix-org.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-en-GB.matrix-org.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPhone-15-pseudo.Credentials-Entered.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-pseudo.Credentials-Entered.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPhone-15-pseudo.Credentials-Entered.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-pseudo.Credentials-Entered.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPhone-15-pseudo.OIDC-Fallback.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-pseudo.OIDC-Fallback.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPhone-15-pseudo.OIDC-Fallback.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-pseudo.OIDC-Fallback.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPhone-15-pseudo.Unsupported.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-pseudo.Unsupported.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPhone-15-pseudo.Unsupported.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-pseudo.Unsupported.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPhone-15-pseudo.matrix-org.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-pseudo.matrix-org.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPhone-15-pseudo.matrix-org.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-pseudo.matrix-org.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPad-en-GB.1.png new file mode 100644 index 0000000000..01a3df526a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:211cac8155e25dd9beb17751a93bebfd37892c00ff739e863af7f4a91f62bb50 +size 108033 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPad-pseudo.1.png new file mode 100644 index 0000000000..a049a98ca0 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d7a41af9a189d0f5f791e0225008d19e11140a9e6af7a672cfef31771663eed8 +size 108741 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..1f1b8e36be --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d5a42c7bf3d6d632e50cd7b9b9bafe7febcd7d5ba40122f58a7833a3b2866921 +size 67960 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..d28527db14 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4c8266a83c333124c0baeb82377174eff028fac8cdb9db827d1ba74c3719a3b1 +size 68653 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_mapLibreStaticMapView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mapLibreStaticMapView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_mapLibreStaticMapView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_mapLibreStaticMapView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_mapLibreStaticMapView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mapLibreStaticMapView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_mapLibreStaticMapView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_mapLibreStaticMapView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_mapLibreStaticMapView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mapLibreStaticMapView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_mapLibreStaticMapView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_mapLibreStaticMapView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_mapLibreStaticMapView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mapLibreStaticMapView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_mapLibreStaticMapView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_mapLibreStaticMapView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPad-en-GB.1.png new file mode 100644 index 0000000000..850c949fee --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e8f69de3a43c8fda4a4d2ccf3302b8a1be36371a804be72945a1e993a7bea51 +size 69513 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPad-pseudo.1.png new file mode 100644 index 0000000000..850c949fee --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e8f69de3a43c8fda4a4d2ccf3302b8a1be36371a804be72945a1e993a7bea51 +size 69513 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..aec45a7c3b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e30b3071e1cdc60ab4f80bbf87d6fb88b4f1027ec2d18ebad669ee8d21fc4e9d +size 29090 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..aec45a7c3b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e30b3071e1cdc60ab4f80bbf87d6fb88b4f1027ec2d18ebad669ee8d21fc4e9d +size 29090 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-en-GB.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-en-GB.2.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-en-GB.2.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-en-GB.2.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-pseudo.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-pseudo.2.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-pseudo.2.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-pseudo.2.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-15-en-GB.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-16-en-GB.2.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-15-en-GB.2.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-16-en-GB.2.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-15-pseudo.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-16-pseudo.2.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-15-pseudo.2.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-16-pseudo.2.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.1.png diff --git a/PreviewTests/__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 similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying-in-thread.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying-in-thread.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying-in-thread.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying-in-thread.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying-in-thread.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying-in-thread.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPhone-15-en-GB.Replying-in-thread.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.Replying-in-thread.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPhone-15-en-GB.Replying-in-thread.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.Replying-in-thread.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPhone-15-en-GB.Replying.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.Replying.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPhone-15-en-GB.Replying.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.Replying.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPhone-15-pseudo.Replying-in-thread.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.Replying-in-thread.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPhone-15-pseudo.Replying-in-thread.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.Replying-in-thread.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPhone-15-pseudo.Replying.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.Replying.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_messageComposer-iPhone-15-pseudo.Replying.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.Replying.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageComposerTextField-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposerTextField-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_messageComposerTextField-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposerTextField-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageComposerTextField-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposerTextField-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_messageComposerTextField-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposerTextField-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageComposerTextField-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposerTextField-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_messageComposerTextField-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposerTextField-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageComposerTextField-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposerTextField-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_messageComposerTextField-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposerTextField-iPhone-16-pseudo.1.png 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 new file mode 100644 index 0000000000..07c4385f19 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7001c732a5f38e3b8093488f80504a474c0b8f4f494e68793029f387047522e8 +size 152484 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..b97167e9de --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d213faa018f71016ebc6f31691ac3cbf97849e8a739937d9e351b92bef7877c +size 154392 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 new file mode 100644 index 0000000000..9bb41b57cf --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ee5ecf468c941282295014187f8fc03929c122f343465113496e20a8cca738d6 +size 101988 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 new file mode 100644 index 0000000000..559fd39e1b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:53268d051594a0dd4250a79b5b3093a4f57f4104250c990e6bb276c751093b94 +size 101810 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.Custom-Attachment.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.Custom-Attachment.png new file mode 100644 index 0000000000..ee3043108e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.Custom-Attachment.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ab0efa7ad7ced4f257adf46064a78cba4b07b61e07610b94372aea205803d85d +size 72247 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.Custom-Text.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.Custom-Text.png new file mode 100644 index 0000000000..c7ffef45cc --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.Custom-Text.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:246ccf3dab763371a54430473e36629b65b74b66134c3ac547d2a3499dbc193a +size 75057 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.SwiftUI-Default-Text.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.SwiftUI-Default-Text.png new file mode 100644 index 0000000000..e62783d732 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.SwiftUI-Default-Text.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:51c983cbadb2a9e25cb4528abda91e77ae6540dd15347e3e475371f2f5ea7ef1 +size 75057 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.With-block-quote.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.With-block-quote.png new file mode 100644 index 0000000000..cc23204d43 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.With-block-quote.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:758cb2a11e32499693cf9b1d3ce4652769d402b89543c823d2c944a363d499fe +size 92951 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.With-list.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.With-list.png new file mode 100644 index 0000000000..face1940a8 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.With-list.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bdf72759297ba0bd010c6ef0379db71ba710397cb0f660bc87e72433453b54f9 +size 79542 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.Custom-Attachment.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.Custom-Attachment.png new file mode 100644 index 0000000000..ee3043108e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.Custom-Attachment.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ab0efa7ad7ced4f257adf46064a78cba4b07b61e07610b94372aea205803d85d +size 72247 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.Custom-Text.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.Custom-Text.png new file mode 100644 index 0000000000..c7ffef45cc --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.Custom-Text.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:246ccf3dab763371a54430473e36629b65b74b66134c3ac547d2a3499dbc193a +size 75057 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.SwiftUI-Default-Text.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.SwiftUI-Default-Text.png new file mode 100644 index 0000000000..e62783d732 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.SwiftUI-Default-Text.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:51c983cbadb2a9e25cb4528abda91e77ae6540dd15347e3e475371f2f5ea7ef1 +size 75057 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.With-block-quote.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.With-block-quote.png new file mode 100644 index 0000000000..cc23204d43 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.With-block-quote.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:758cb2a11e32499693cf9b1d3ce4652769d402b89543c823d2c944a363d499fe +size 92951 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.With-list.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.With-list.png new file mode 100644 index 0000000000..face1940a8 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.With-list.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bdf72759297ba0bd010c6ef0379db71ba710397cb0f660bc87e72433453b54f9 +size 79542 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-en-GB.Custom-Attachment.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-en-GB.Custom-Attachment.png new file mode 100644 index 0000000000..c7dd35a923 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-en-GB.Custom-Attachment.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e8df10b2bbfcf7242bff019ca058bbeb0ed948b830e9db0aeb9516d03201431e +size 31481 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-en-GB.Custom-Text.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-en-GB.Custom-Text.png new file mode 100644 index 0000000000..761b51b2f1 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-en-GB.Custom-Text.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c42a0011099843cc8a21a05511b8c1cf174c0f3a19c32bc5521c167a9d3fae32 +size 42627 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-en-GB.SwiftUI-Default-Text.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-en-GB.SwiftUI-Default-Text.png new file mode 100644 index 0000000000..806ee3ca5f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-en-GB.SwiftUI-Default-Text.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bbcaead45dbd525d19def5b2abe72604865aab22b5d1ae436c41a7868e6085cc +size 42698 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-en-GB.With-block-quote.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-en-GB.With-block-quote.png new file mode 100644 index 0000000000..3281857800 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-en-GB.With-block-quote.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:84731eed2f5233bfc1d50b1978701b3a66326fa0fa1d8afac53d8724cfcb78f3 +size 54665 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-en-GB.With-list.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-en-GB.With-list.png new file mode 100644 index 0000000000..163ad27071 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-en-GB.With-list.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:91d608f5ded05640756d74ea89883689f193eae05217a4d5ae1444108169d805 +size 38950 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-pseudo.Custom-Attachment.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-pseudo.Custom-Attachment.png new file mode 100644 index 0000000000..c7dd35a923 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-pseudo.Custom-Attachment.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e8df10b2bbfcf7242bff019ca058bbeb0ed948b830e9db0aeb9516d03201431e +size 31481 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-pseudo.Custom-Text.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-pseudo.Custom-Text.png new file mode 100644 index 0000000000..761b51b2f1 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-pseudo.Custom-Text.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c42a0011099843cc8a21a05511b8c1cf174c0f3a19c32bc5521c167a9d3fae32 +size 42627 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-pseudo.SwiftUI-Default-Text.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-pseudo.SwiftUI-Default-Text.png new file mode 100644 index 0000000000..806ee3ca5f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-pseudo.SwiftUI-Default-Text.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bbcaead45dbd525d19def5b2abe72604865aab22b5d1ae436c41a7868e6085cc +size 42698 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-pseudo.With-block-quote.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-pseudo.With-block-quote.png new file mode 100644 index 0000000000..3281857800 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-pseudo.With-block-quote.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:84731eed2f5233bfc1d50b1978701b3a66326fa0fa1d8afac53d8724cfcb78f3 +size 54665 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-pseudo.With-list.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-pseudo.With-list.png new file mode 100644 index 0000000000..163ad27071 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageText-iPhone-16-pseudo.With-list.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:91d608f5ded05640756d74ea89883689f193eae05217a4d5ae1444108169d805 +size 38950 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationPermissionsScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationPermissionsScreen-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationPermissionsScreen-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationPermissionsScreen-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationPermissionsScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationPermissionsScreen-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationPermissionsScreen-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationPermissionsScreen-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationPermissionsScreen-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationPermissionsScreen-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationPermissionsScreen-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationPermissionsScreen-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationPermissionsScreen-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationPermissionsScreen-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationPermissionsScreen-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationPermissionsScreen-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-en-GB.Applying-change.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-en-GB.Applying-change.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-en-GB.Applying-change.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-en-GB.Applying-change.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-en-GB.Direct-Chats.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-en-GB.Direct-Chats.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-en-GB.Direct-Chats.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-en-GB.Direct-Chats.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-en-GB.Group-Chats-Without-Disclaimer.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-en-GB.Group-Chats-Without-Disclaimer.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-en-GB.Group-Chats-Without-Disclaimer.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-en-GB.Group-Chats-Without-Disclaimer.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-en-GB.Group-Chats.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-en-GB.Group-Chats.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-en-GB.Group-Chats.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-en-GB.Group-Chats.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-pseudo.Applying-change.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-pseudo.Applying-change.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-pseudo.Applying-change.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-pseudo.Applying-change.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-pseudo.Direct-Chats.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-pseudo.Direct-Chats.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-pseudo.Direct-Chats.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-pseudo.Direct-Chats.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-pseudo.Group-Chats-Without-Disclaimer.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-pseudo.Group-Chats-Without-Disclaimer.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-pseudo.Group-Chats-Without-Disclaimer.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-pseudo.Group-Chats-Without-Disclaimer.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-pseudo.Group-Chats.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-pseudo.Group-Chats.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-pseudo.Group-Chats.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPad-pseudo.Group-Chats.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-15-en-GB.Applying-change.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-16-en-GB.Applying-change.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-15-en-GB.Applying-change.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-16-en-GB.Applying-change.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-15-en-GB.Direct-Chats.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-16-en-GB.Direct-Chats.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-15-en-GB.Direct-Chats.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-16-en-GB.Direct-Chats.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-15-en-GB.Group-Chats-Without-Disclaimer.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-16-en-GB.Group-Chats-Without-Disclaimer.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-15-en-GB.Group-Chats-Without-Disclaimer.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-16-en-GB.Group-Chats-Without-Disclaimer.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-15-en-GB.Group-Chats.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-16-en-GB.Group-Chats.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-15-en-GB.Group-Chats.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-16-en-GB.Group-Chats.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-15-pseudo.Applying-change.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-16-pseudo.Applying-change.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-15-pseudo.Applying-change.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-16-pseudo.Applying-change.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-15-pseudo.Direct-Chats.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-16-pseudo.Direct-Chats.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-15-pseudo.Direct-Chats.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-16-pseudo.Direct-Chats.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-15-pseudo.Group-Chats-Without-Disclaimer.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-16-pseudo.Group-Chats-Without-Disclaimer.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-15-pseudo.Group-Chats-Without-Disclaimer.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-16-pseudo.Group-Chats-Without-Disclaimer.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-15-pseudo.Group-Chats.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-16-pseudo.Group-Chats.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-15-pseudo.Group-Chats.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreen-iPhone-16-pseudo.Group-Chats.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPhone-16-pseudo.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-en-GB.1.png new file mode 100644 index 0000000000..53d9437e81 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:04a039144c38ee6a54b2a67fc8a6a4759b31767eaea9d210adb2b4ee118693e3 +size 146058 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-en-GB.Configuration-mismatch.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-en-GB.Configuration-mismatch.png new file mode 100644 index 0000000000..f630cfd3cf --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-en-GB.Configuration-mismatch.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aeb8e86177906f0839e3408f9ecd481735413b5abbd4af4391e09b8a2e89f7fc +size 117372 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..42d6d29dc7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7acd49824cffe16d29167614c3f91a01572567d405e65cb478b1b2025bcc44bc +size 165008 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-pseudo.Configuration-mismatch.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-pseudo.Configuration-mismatch.png new file mode 100644 index 0000000000..4fb32cb74b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-pseudo.Configuration-mismatch.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b4ca4dfbba75071e5d8de0e0c6f2869fbceeeee3faf03a86bc590d027424192b +size 145318 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 new file mode 100644 index 0000000000..6159caa6ad --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:773528462e21578b18913b3696f8614d8679645fb62c92f2344b5852ba9638a3 +size 92329 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-16-en-GB.Configuration-mismatch.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-16-en-GB.Configuration-mismatch.png new file mode 100644 index 0000000000..16aff46847 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-16-en-GB.Configuration-mismatch.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e6f03c20e7b9f8f0afbd33de535b7b4e1284c9da1f2a2050b92037f1760fd78 +size 72028 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 new file mode 100644 index 0000000000..4fc0a1cc0f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f31ea41a2793dcc67ae3dfd3c54014bd9bc15352fe0e2c8742cf62435be45ed +size 126574 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-16-pseudo.Configuration-mismatch.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-16-pseudo.Configuration-mismatch.png new file mode 100644 index 0000000000..1b88e088c6 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-16-pseudo.Configuration-mismatch.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf3aa18c740290200b375c20c3c1aabff8625e23654ae568212e7015476cf456 +size 109170 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pINTextField-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pINTextField-iPad-en-GB.1.png new file mode 100644 index 0000000000..99da4029b3 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pINTextField-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5c58b8daa0378a32b6e1e062333838c6395e52bfb1c95f788457965d23e83281 +size 108232 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pINTextField-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pINTextField-iPad-pseudo.1.png new file mode 100644 index 0000000000..99da4029b3 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pINTextField-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5c58b8daa0378a32b6e1e062333838c6395e52bfb1c95f788457965d23e83281 +size 108232 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pINTextField-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pINTextField-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..066b0ac8dc --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pINTextField-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c79d044092ae68911550f15ae135d79bf5536a5f7b397a4b7f1fbe4e45e762c +size 65452 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pINTextField-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pINTextField-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..066b0ac8dc --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pINTextField-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c79d044092ae68911550f15ae135d79bf5536a5f7b397a4b7f1fbe4e45e762c +size 65452 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_paginationIndicatorRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_paginationIndicatorRoomTimelineView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_paginationIndicatorRoomTimelineView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_paginationIndicatorRoomTimelineView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_paginationIndicatorRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_paginationIndicatorRoomTimelineView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_paginationIndicatorRoomTimelineView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_paginationIndicatorRoomTimelineView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_paginationIndicatorRoomTimelineView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_paginationIndicatorRoomTimelineView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_paginationIndicatorRoomTimelineView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_paginationIndicatorRoomTimelineView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_paginationIndicatorRoomTimelineView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_paginationIndicatorRoomTimelineView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_paginationIndicatorRoomTimelineView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_paginationIndicatorRoomTimelineView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPad-en-GB.All-Users.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPad-en-GB.All-Users.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPad-en-GB.All-Users.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPad-en-GB.All-Users.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPad-en-GB.Loaded-Long-Own.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPad-en-GB.Loaded-Long-Own.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPad-en-GB.Loaded-Long-Own.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPad-en-GB.Loaded-Long-Own.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPad-en-GB.Loaded-Long.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPad-en-GB.Loaded-Long.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPad-en-GB.Loaded-Long.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPad-en-GB.Loaded-Long.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPad-en-GB.Loading-Own.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPad-en-GB.Loading-Own.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPad-en-GB.Loading-Own.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPad-en-GB.Loading-Own.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPad-en-GB.Loading.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPad-en-GB.Loading.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPad-en-GB.Loading.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPad-en-GB.Loading.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPad-pseudo.All-Users.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPad-pseudo.All-Users.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPad-pseudo.All-Users.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPad-pseudo.All-Users.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPad-pseudo.Loaded-Long-Own.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPad-pseudo.Loaded-Long-Own.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPad-pseudo.Loaded-Long-Own.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPad-pseudo.Loaded-Long-Own.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPad-pseudo.Loaded-Long.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPad-pseudo.Loaded-Long.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPad-pseudo.Loaded-Long.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPad-pseudo.Loaded-Long.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPad-pseudo.Loading-Own.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPad-pseudo.Loading-Own.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPad-pseudo.Loading-Own.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPad-pseudo.Loading-Own.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPad-pseudo.Loading.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPad-pseudo.Loading.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPad-pseudo.Loading.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPad-pseudo.Loading.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPhone-15-en-GB.All-Users.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPhone-16-en-GB.All-Users.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPhone-15-en-GB.All-Users.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPhone-16-en-GB.All-Users.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPhone-15-en-GB.Loaded-Long-Own.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPhone-16-en-GB.Loaded-Long-Own.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPhone-15-en-GB.Loaded-Long-Own.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPhone-16-en-GB.Loaded-Long-Own.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPhone-15-en-GB.Loaded-Long.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPhone-16-en-GB.Loaded-Long.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPhone-15-en-GB.Loaded-Long.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPhone-16-en-GB.Loaded-Long.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPhone-15-en-GB.Loading-Own.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPhone-16-en-GB.Loading-Own.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPhone-15-en-GB.Loading-Own.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPhone-16-en-GB.Loading-Own.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPhone-15-en-GB.Loading.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPhone-16-en-GB.Loading.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPhone-15-en-GB.Loading.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPhone-16-en-GB.Loading.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPhone-15-pseudo.All-Users.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPhone-16-pseudo.All-Users.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPhone-15-pseudo.All-Users.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPhone-16-pseudo.All-Users.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPhone-15-pseudo.Loaded-Long-Own.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPhone-16-pseudo.Loaded-Long-Own.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPhone-15-pseudo.Loaded-Long-Own.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPhone-16-pseudo.Loaded-Long-Own.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPhone-15-pseudo.Loaded-Long.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPhone-16-pseudo.Loaded-Long.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPhone-15-pseudo.Loaded-Long.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPhone-16-pseudo.Loaded-Long.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPhone-15-pseudo.Loading-Own.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPhone-16-pseudo.Loading-Own.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPhone-15-pseudo.Loading-Own.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPhone-16-pseudo.Loading-Own.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPhone-15-pseudo.Loading.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPhone-16-pseudo.Loading.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_pillView-iPhone-15-pseudo.Loading.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_pillView-iPhone-16-pseudo.Loading.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPad-en-GB.Empty.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPad-en-GB.Empty.png new file mode 100644 index 0000000000..0bd69fb870 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPad-en-GB.Empty.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1cb783734a65fa84449c22e1c2df60151ff03e17a9a6d7f7ada2568be24a08c9 +size 96586 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPad-pseudo.Empty.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPad-pseudo.Empty.png new file mode 100644 index 0000000000..ab452f8252 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPad-pseudo.Empty.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cb254d38a6bd5eacf43837e030ec62fa12489daa4f4b8b838b71bec9b7a469e3 +size 112922 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPhone-16-en-GB.Empty.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPhone-16-en-GB.Empty.png new file mode 100644 index 0000000000..74d01ed9ca --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPhone-16-en-GB.Empty.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3b35ed703fbe9bdcbd7fbc637f0954ceb66a316e534cc331920fab34522758e7 +size 56642 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPhone-16-pseudo.Empty.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPhone-16-pseudo.Empty.png new file mode 100644 index 0000000000..082c188f48 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPhone-16-pseudo.Empty.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:859d4cad624b9556ad55f8c4d39badd26512237c280ee9affe44321c162cba18 +size 76416 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPad-en-GB.1.png new file mode 100644 index 0000000000..8772a3ca5d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f1c0f5c4908a4846f72c3842054a072b28a403c4e0a58094ce2ec2197da3c3c5 +size 140801 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPad-pseudo.1.png new file mode 100644 index 0000000000..8338573be1 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:faa4dade1cd81194b56c82bb90c95b7cd933db10735baf6718037593f90c21ab +size 168534 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..23a17a9009 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:675bac92ca94414ae552689d0dfe2d4eacbb756ab065a859a954c0e392917933 +size 85919 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..81aab63246 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:515384fc8cabd0e83238b2205d2df61be08d32a42027dedf6099c36e60c6bbdb +size 100273 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPad-en-GB.1.png new file mode 100644 index 0000000000..5e3a44679f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:05df896a2a8c47254923f58f9bf890648a75a252e34e6aeec9e4a3cbb3fb206d +size 12286 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPad-pseudo.1.png new file mode 100644 index 0000000000..260b05db74 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:82cf4b22f5fe8cc6d10536a4761d6a94d3b3e9ebe802674f79a5d1f3487a6cb9 +size 16182 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..524b988b7d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:84976d7df074f1a445c8e27948b1b5481a9f2d3a872bc0f6c2619e2edb311b40 +size 8784 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..a919519295 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f6a4b38154465436c1f0ba91c7742dda3fce333fbcf76fa621edef78f450723c +size 15327 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderAvatarImage-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderAvatarImage-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_placeholderAvatarImage-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderAvatarImage-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderAvatarImage-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderAvatarImage-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_placeholderAvatarImage-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderAvatarImage-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderAvatarImage-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderAvatarImage-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_placeholderAvatarImage-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderAvatarImage-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderAvatarImage-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderAvatarImage-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_placeholderAvatarImage-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderAvatarImage-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-en-GB.Screen.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-en-GB.Screen.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-en-GB.Screen.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-en-GB.Screen.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-en-GB.Split-View.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-en-GB.Split-View.png new file mode 100644 index 0000000000..8f238ee1db --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-en-GB.Split-View.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:82f598c32db0e73ec5a4b575cb216c824b734f48d761bbb61bc40539dfd3be0e +size 214682 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-pseudo.Screen.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-en-GB.With-background.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-pseudo.Screen.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-en-GB.With-background.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-pseudo.Screen.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-pseudo.Screen.png new file mode 100644 index 0000000000..d7d93829c7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-pseudo.Screen.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:61f6e4e2777ed816cee39e9a833ecd4e8591f04056bf06da055f402db5048bd2 +size 192719 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-pseudo.Split-View.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-pseudo.Split-View.png new file mode 100644 index 0000000000..8f238ee1db --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-pseudo.Split-View.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:82f598c32db0e73ec5a4b575cb216c824b734f48d761bbb61bc40539dfd3be0e +size 214682 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-pseudo.With-background.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-pseudo.With-background.png new file mode 100644 index 0000000000..d7d93829c7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-pseudo.With-background.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:61f6e4e2777ed816cee39e9a833ecd4e8591f04056bf06da055f402db5048bd2 +size 192719 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-15-en-GB.Screen.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-16-en-GB.Screen.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-15-en-GB.Screen.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-16-en-GB.Screen.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-16-en-GB.Split-View.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-16-en-GB.Split-View.png new file mode 100644 index 0000000000..3de9e4f423 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-16-en-GB.Split-View.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:305b1b6a9e5816174b64fd2819b79a7489405b0f7eef86d47b4471f6a117ba99 +size 39207 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-15-en-GB.With-background.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-16-en-GB.With-background.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-15-en-GB.With-background.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-16-en-GB.With-background.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-15-pseudo.Screen.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-16-pseudo.Screen.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-15-pseudo.Screen.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-16-pseudo.Screen.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-16-pseudo.Split-View.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-16-pseudo.Split-View.png new file mode 100644 index 0000000000..3de9e4f423 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-16-pseudo.Split-View.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:305b1b6a9e5816174b64fd2819b79a7489405b0f7eef86d47b4471f6a117ba99 +size 39207 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-15-pseudo.With-background.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-16-pseudo.With-background.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-15-pseudo.With-background.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-16-pseudo.With-background.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-en-GB.Edit.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-en-GB.Edit.png new file mode 100644 index 0000000000..85c988c801 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-en-GB.Edit.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ccafda1521bc9a2620fb3698b0f743fa90c91b7b83b8fb6559f5862e1acbf46e +size 121014 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 new file mode 100644 index 0000000000..c3d3f73b59 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-en-GB.New.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a4304db38a7991bcaa33d1266968f023811bc2184fdf0b34b1ecc27b5a841d2 +size 122158 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-pseudo.Edit.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-pseudo.Edit.png new file mode 100644 index 0000000000..7fd3ffd2bb --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-pseudo.Edit.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1e6b25c989524f3a1e89f2c85e8e0038c26cff7861b5f7858b7d76adbcf92a07 +size 126701 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-pseudo.New.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-pseudo.New.png new file mode 100644 index 0000000000..802cc7f1bd --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-pseudo.New.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9e45b9a0ba61580509d623751b5fba479a39e2d8394ea46b0b1af52c08581822 +size 132210 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 new file mode 100644 index 0000000000..408cef51f5 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-en-GB.Edit.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:08afa1f613cec282b2e33635cd9c3f27b261551f3e3fca8abb7f246da3b872bd +size 73311 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 new file mode 100644 index 0000000000..1a66842d58 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-en-GB.New.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:443329bbf5362a9a96ac46b96b6888a324550501a9f23e073f2319ac40501c0d +size 71836 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 new file mode 100644 index 0000000000..ff5e858af7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-pseudo.Edit.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26559d5ff08ce908efae27b352af8aabeca49f4a8b78f5f43582def38b27cf6e +size 83493 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 new file mode 100644 index 0000000000..1a7a5ce208 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-pseudo.New.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ba37435702fee3ee5e125ed3300efe64c878c49dedf853371de7dabf8b30332 +size 88037 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollOptionView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollOptionView-iPad-en-GB.1.png new file mode 100644 index 0000000000..ba573c6e30 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollOptionView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3c77bb68c553b4124fb19c8630863becca35fc0cfb8bbbb85ac862d65fdad3dd +size 90837 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollOptionView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollOptionView-iPad-pseudo.1.png new file mode 100644 index 0000000000..9b1e2bdc07 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollOptionView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:51b7e5479c855b0702cdc8f0fa985a46d8c72dce3fde9fb8170b97bb38ece4c5 +size 97598 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollOptionView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollOptionView-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..dab8a0a57b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollOptionView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:36374bfa651aa0b8584c54e97e60df563cb2f23fd5c0e5687f68bb5cf0796bb0 +size 48886 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollOptionView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollOptionView-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..d70a4be61c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollOptionView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f95df9ef11bb6ad896ab56b3ca8e3627efac2806aeb754f6947bc9829721eef +size 57851 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Creator-disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Creator-disclosed-Bubble.png new file mode 100644 index 0000000000..4ff204d996 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Creator-disclosed-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5588f1b5c3673c7637b0d54b1b81f84ebdbcffef54595e13c2769a9ab49ddbbd +size 120582 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Creator-no-votes-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Creator-no-votes-Bubble.png new file mode 100644 index 0000000000..ed293de56c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Creator-no-votes-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fdd82d802c100ca12b7d7cccc36c4d69950b8908be64abc0365409bd188c9a3c +size 120334 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Disclosed-Bubble.png new file mode 100644 index 0000000000..b0a705831f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Disclosed-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f84ce97f1de03675d8f833127d0da7e8ed1a00aaaf4c3a01a82bd6c174ad9a5f +size 115200 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Ended-Disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Ended-Disclosed-Bubble.png new file mode 100644 index 0000000000..23fa64585b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Ended-Disclosed-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6af065aa0746db5dd657ad05bff5ca29f48bc3e0d47a776cbbb7199f705f8373 +size 114952 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Ended-Undisclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Ended-Undisclosed-Bubble.png new file mode 100644 index 0000000000..23fa64585b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Ended-Undisclosed-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6af065aa0746db5dd657ad05bff5ca29f48bc3e0d47a776cbbb7199f705f8373 +size 114952 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Preview.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Preview.png new file mode 100644 index 0000000000..37d74d55b1 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Preview.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e794544b48d147d620fb3d12365d9b265ed03e23dda7f191662555f3431ee595 +size 79267 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Undisclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Undisclosed-Bubble.png new file mode 100644 index 0000000000..1ab875b97a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Undisclosed-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:47365a8ce3aacf6432d147ba27ecee5d55a4b7a7415794761e7387e23c222e78 +size 111787 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Creator-disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Creator-disclosed-Bubble.png new file mode 100644 index 0000000000..06461de6ab --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Creator-disclosed-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6f09fd7c993fdb7034a0c52ad1741a5cf05c0d58b32c454cf97fe68a6c8cacca +size 134951 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Creator-no-votes-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Creator-no-votes-Bubble.png new file mode 100644 index 0000000000..03d0dc8825 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Creator-no-votes-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3f9a7e25d1dddfab55108b9894feb4d50adfe5e9f33475d494581df2877b36d9 +size 134501 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Disclosed-Bubble.png new file mode 100644 index 0000000000..e701ba3b70 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Disclosed-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aed6092acae427341404cb3c3203fa920544f936de5fb0bff9c4a3150f9af56b +size 130082 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Ended-Disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Ended-Disclosed-Bubble.png new file mode 100644 index 0000000000..6a81f698ff --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Ended-Disclosed-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:33442a0da97a6b366f9efe8e7fea603ad0de39bd8bf352d6e219435050b3c4b9 +size 128547 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Ended-Undisclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Ended-Undisclosed-Bubble.png new file mode 100644 index 0000000000..6a81f698ff --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Ended-Undisclosed-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:33442a0da97a6b366f9efe8e7fea603ad0de39bd8bf352d6e219435050b3c4b9 +size 128547 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Preview.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Preview.png new file mode 100644 index 0000000000..37d74d55b1 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Preview.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e794544b48d147d620fb3d12365d9b265ed03e23dda7f191662555f3431ee595 +size 79267 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Undisclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Undisclosed-Bubble.png new file mode 100644 index 0000000000..be9a98a081 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Undisclosed-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:03257dc02e700e403d229736219ac6e9ff22c37756a7f90a60134a1e3ee58848 +size 117042 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Creator-disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Creator-disclosed-Bubble.png new file mode 100644 index 0000000000..155a221c9f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Creator-disclosed-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9898c8ed3dca614fcd1a0cc5dc8245057e4c098312c8f7d5a27e32642bb68293 +size 73383 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Creator-no-votes-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Creator-no-votes-Bubble.png new file mode 100644 index 0000000000..aaff342f70 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Creator-no-votes-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8d45a079df17a7e9bda5bfacdbdcafedba7e7f2863ecd32fe7781ecf65153f11 +size 73162 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Disclosed-Bubble.png new file mode 100644 index 0000000000..6e0dfe2f25 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Disclosed-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0c00cde6d7bbcf3b8c295cddcc755adc1a1ec47a38624eda37b0a73f03c455c0 +size 68530 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Ended-Disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Ended-Disclosed-Bubble.png new file mode 100644 index 0000000000..a66d78853b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Ended-Disclosed-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:40eda3506181416da579a84b715a5602f1b0c7397eb54e56215c90c6f8f1d0a4 +size 68166 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Ended-Undisclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Ended-Undisclosed-Bubble.png new file mode 100644 index 0000000000..a66d78853b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Ended-Undisclosed-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:40eda3506181416da579a84b715a5602f1b0c7397eb54e56215c90c6f8f1d0a4 +size 68166 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Preview.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Preview.png new file mode 100644 index 0000000000..b3d5d0a0dd --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Preview.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3fb34cdbfd8b96f150febcf956c6dde8bc28052679ad8d216dcd47bda58c1adf +size 39188 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Undisclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Undisclosed-Bubble.png new file mode 100644 index 0000000000..480292a7e0 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Undisclosed-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a67811455cada6f94ac7888ef2759d30f3d0aa002ce566f6f24cfcf3c26d89b +size 67083 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Creator-disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Creator-disclosed-Bubble.png new file mode 100644 index 0000000000..baf03bd952 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Creator-disclosed-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:771f11cd8317781b17a52cd09af602198ee49e0c57f3248572c48b7a149aeb9b +size 86548 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Creator-no-votes-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Creator-no-votes-Bubble.png new file mode 100644 index 0000000000..48fae3f985 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Creator-no-votes-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b78407f39f5f594ab4d2abc44e78b0174f65f7985ef6fc5b2698072047e06d24 +size 85908 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Disclosed-Bubble.png new file mode 100644 index 0000000000..620a8b93d1 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Disclosed-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d804f0beb15981af0fc1944ad13e7fa508282211116f23a4774d8e56d6f16f89 +size 81762 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Ended-Disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Ended-Disclosed-Bubble.png new file mode 100644 index 0000000000..017801eeb9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Ended-Disclosed-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:050679f93ac6565b363a1118a0f40c8f2ba353a5e3a0db81a5425e5949b24b2f +size 86709 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Ended-Undisclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Ended-Undisclosed-Bubble.png new file mode 100644 index 0000000000..017801eeb9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Ended-Undisclosed-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:050679f93ac6565b363a1118a0f40c8f2ba353a5e3a0db81a5425e5949b24b2f +size 86709 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Preview.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Preview.png new file mode 100644 index 0000000000..b3d5d0a0dd --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Preview.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3fb34cdbfd8b96f150febcf956c6dde8bc28052679ad8d216dcd47bda58c1adf +size 39188 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Undisclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Undisclosed-Bubble.png new file mode 100644 index 0000000000..96c04b9d68 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Undisclosed-Bubble.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a36febee4c51f0ca52d880e85ddd73cb3ad52ed653546f5b96ea5615bc0257d +size 73227 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Creator-disclosed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Creator-disclosed.png new file mode 100644 index 0000000000..c7aff32565 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Creator-disclosed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:96b83fda3e2e925da58c0421cb30e1844db7740a274e70c50210c43e605b5bc0 +size 109828 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Creator-no-votes.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Creator-no-votes.png new file mode 100644 index 0000000000..bc9b214788 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Creator-no-votes.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:19fa3722e6d1e410feb5119ce3cdc3190491b75aa27867f4f9ef312869f5cf54 +size 109338 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Disclosed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Disclosed.png new file mode 100644 index 0000000000..cf4c13c50b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Disclosed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aacd22075f89d255b91d489cf9707a3facf8536f65bb55b427f748864acd482c +size 104227 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Ended-Disclosed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Ended-Disclosed.png new file mode 100644 index 0000000000..de3788fc66 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Ended-Disclosed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5d094fa7c172b1b35df67a9d3b3038d93f97641c42eb4c0f333675b92bff53e2 +size 104702 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Ended-Undisclosed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Ended-Undisclosed.png new file mode 100644 index 0000000000..de3788fc66 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Ended-Undisclosed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5d094fa7c172b1b35df67a9d3b3038d93f97641c42eb4c0f333675b92bff53e2 +size 104702 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Preview.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Preview.png new file mode 100644 index 0000000000..b6bb337ec6 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Preview.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:343fd848d843b7bd8d26e491fc36f81b69273bdf2dd7febee4cf4ab5b1148dd8 +size 74964 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Undisclosed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Undisclosed.png new file mode 100644 index 0000000000..eb59c3b451 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Undisclosed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:679bdc9c11255fd0a1f99e319428ddbf655e96ed734c9c60dc45a2268c41b274 +size 101057 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Creator-disclosed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Creator-disclosed.png new file mode 100644 index 0000000000..8dabcebd69 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Creator-disclosed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b17bba2f498be4740873c7f89442df5881ab8abf71e54fdf15276328745e78cd +size 124211 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Creator-no-votes.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Creator-no-votes.png new file mode 100644 index 0000000000..bb952200f3 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Creator-no-votes.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:776de8716f389fec662c6bc51cdf866f2125e3a152d1cc67e1c8903a0982f370 +size 123482 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Disclosed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Disclosed.png new file mode 100644 index 0000000000..1671261519 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Disclosed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1da506d52873f3f9b174e2653cfb85ca80c8b6866c64367346bd2b2af531e138 +size 118615 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Ended-Disclosed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Ended-Disclosed.png new file mode 100644 index 0000000000..69905ad4ed --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Ended-Disclosed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:904e2f570e6a12cb218a94dd0e4bc9e28153f11c9d15a0f4e7342a0b2369361c +size 118574 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Ended-Undisclosed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Ended-Undisclosed.png new file mode 100644 index 0000000000..69905ad4ed --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Ended-Undisclosed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:904e2f570e6a12cb218a94dd0e4bc9e28153f11c9d15a0f4e7342a0b2369361c +size 118574 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Preview.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Preview.png new file mode 100644 index 0000000000..b6bb337ec6 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Preview.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:343fd848d843b7bd8d26e491fc36f81b69273bdf2dd7febee4cf4ab5b1148dd8 +size 74964 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Undisclosed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Undisclosed.png new file mode 100644 index 0000000000..b0775b7cdb --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Undisclosed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c55ec9c5ef434beaba426263c522729f1059f1962c2e2cb2ad103169e55f4bb1 +size 105680 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Creator-disclosed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Creator-disclosed.png new file mode 100644 index 0000000000..9e41ee4055 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Creator-disclosed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:50cbea7cbed75a833e8e51025862354edf351bb586178b9612cfa80d71d3101c +size 63855 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Creator-no-votes.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Creator-no-votes.png new file mode 100644 index 0000000000..6cb617b437 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Creator-no-votes.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2b4d49de638e4912b171d5d0ada54086059a1df62857158908653b809d3dd712 +size 63363 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Disclosed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Disclosed.png new file mode 100644 index 0000000000..49afce0d0d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Disclosed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89f94b5070012acce638636c708e901ba47a0016bb18708ff418d3a337732963 +size 59453 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Ended-Disclosed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Ended-Disclosed.png new file mode 100644 index 0000000000..b4d69ff9ad --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Ended-Disclosed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26095e491c52cda60b6a8389855863d725e9c3f64e0840e63db4d160ff76c808 +size 59805 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Ended-Undisclosed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Ended-Undisclosed.png new file mode 100644 index 0000000000..b4d69ff9ad --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Ended-Undisclosed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26095e491c52cda60b6a8389855863d725e9c3f64e0840e63db4d160ff76c808 +size 59805 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Preview.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Preview.png new file mode 100644 index 0000000000..8e76fd4fa2 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Preview.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16e27ee37838fe4cf98f5daa55d1cdaa5bb76acb193ae7fae3fa6d89be839bab +size 33677 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Undisclosed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Undisclosed.png new file mode 100644 index 0000000000..6848288301 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-en-GB.Undisclosed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e1a125f0c606731d990fdf5993a3e260b7a43f91e597435f9e7cf3887214ff89 +size 56453 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Creator-disclosed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Creator-disclosed.png new file mode 100644 index 0000000000..f611599914 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Creator-disclosed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aead8444ab77f4c06f58c31c26a6adb85fb0f64c300c7d8b99edaeb253d671fa +size 80666 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Creator-no-votes.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Creator-no-votes.png new file mode 100644 index 0000000000..be387e3ba1 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Creator-no-votes.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a35999015b6ffe48c0a7bd7fadbccfad674b65b23a1e25487fdca18d2e49407c +size 79911 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Disclosed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Disclosed.png new file mode 100644 index 0000000000..a02d3014e5 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Disclosed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1e1c35381f656cb2e58e5b38d1b1f79f07906d2beac8cfee4d5f99fab138d781 +size 75799 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Ended-Disclosed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Ended-Disclosed.png new file mode 100644 index 0000000000..f234d03f14 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Ended-Disclosed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:db19998c21269903b448ce8853796ddd40a14f338fca1ccffe8a7643711eeb29 +size 75666 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Ended-Undisclosed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Ended-Undisclosed.png new file mode 100644 index 0000000000..f234d03f14 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Ended-Undisclosed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:db19998c21269903b448ce8853796ddd40a14f338fca1ccffe8a7643711eeb29 +size 75666 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Preview.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Preview.png new file mode 100644 index 0000000000..8e76fd4fa2 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Preview.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16e27ee37838fe4cf98f5daa55d1cdaa5bb76acb193ae7fae3fa6d89be839bab +size 33677 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Undisclosed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Undisclosed.png new file mode 100644 index 0000000000..bbc8f0ed3c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollView-iPhone-16-pseudo.Undisclosed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ead8d55af23006e3d38834d576e5e7d7e00cf2703c9aca67bca924b1d9057ad +size 61203 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Cancelled.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Cancelled.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Cancelled.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Cancelled.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Connecting.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Connecting.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Connecting.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Connecting.png 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 new file mode 100644 index 0000000000..b64d08e784 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Connection-not-secure.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b7180ebbb140dea72b006104c9e76cdbba65a8281ebf1df2a0037eca668fe75 +size 160208 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Declined.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Declined.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Declined.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Declined.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Device-code.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Device-code.png new file mode 100644 index 0000000000..d1162fdea4 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Device-code.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:52f1f3c88038a0be2f22b2172e64ab0f63f27e6f3e46ccc0e7a447e7ecee2a60 +size 117531 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Device-not-signed-in.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Device-not-signed-in.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Device-not-signed-in.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Device-not-signed-in.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Device-not-supported.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Device-not-supported.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Device-not-supported.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Device-not-supported.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Expired.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Expired.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Expired.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Expired.png 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 new file mode 100644 index 0000000000..9c48c54549 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Initial.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5943061bd68ad5618e722cf2f6d58535e7af0095a480973c80e6dcf9d9b77959 +size 135762 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Invalid.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Invalid.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Invalid.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Invalid.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Linking-unsupported.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Linking-unsupported.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Linking-unsupported.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Linking-unsupported.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.No-Camera-Permission.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.No-Camera-Permission.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.No-Camera-Permission.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.No-Camera-Permission.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Scanning.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Scanning.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Scanning.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Scanning.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Unknown-error.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Unknown-error.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Unknown-error.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Unknown-error.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Verification-code.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Verification-code.png new file mode 100644 index 0000000000..0541ae9c8b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Verification-code.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f291b9089775cddbe19b72b65690db0dc992431df77964f4ee75e438518e079 +size 122826 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Cancelled.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Cancelled.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Cancelled.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Cancelled.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Connecting.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Connecting.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Connecting.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Connecting.png 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 new file mode 100644 index 0000000000..866ff46c68 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Connection-not-secure.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:55be20cbeaaa9fcc334698f0fa741edb9cd3075c66ed74e05874f51632c168ec +size 212452 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Declined.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Declined.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Declined.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Declined.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Device-code.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Device-code.png new file mode 100644 index 0000000000..4a58956410 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Device-code.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e7ef2f40a286ce8f2834841a37ebe3e282efd871786b3bfeca7980ccf8e7deb3 +size 139587 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Device-not-signed-in.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Device-not-signed-in.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Device-not-signed-in.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Device-not-signed-in.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Device-not-supported.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Device-not-supported.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Device-not-supported.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Device-not-supported.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Expired.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Expired.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Expired.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Expired.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Initial.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Initial.png new file mode 100644 index 0000000000..02795455df --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Initial.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d0ec013121390539a9155f4e56685332054dd5b941ff28690f7846ae76c4cb75 +size 163822 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Invalid.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Invalid.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Invalid.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Invalid.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Linking-unsupported.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Linking-unsupported.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Linking-unsupported.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Linking-unsupported.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.No-Camera-Permission.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.No-Camera-Permission.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.No-Camera-Permission.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.No-Camera-Permission.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Scanning.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Scanning.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Scanning.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Scanning.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Unknown-error.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Unknown-error.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Unknown-error.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Unknown-error.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Verification-code.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Verification-code.png new file mode 100644 index 0000000000..d1937a3e80 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Verification-code.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc5811c244211eeeeb091b409a37d6f493ee8a55656ae63cb18f7be546f61bca +size 139318 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Cancelled.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Cancelled.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Cancelled.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Cancelled.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Connecting.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Connecting.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Connecting.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Connecting.png 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 new file mode 100644 index 0000000000..d9875bf827 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Connection-not-secure.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:195ec7a7acb8d36b6533bb0767cb15f1f73a70f1b33be3cc594ebba6b0827b00 +size 108169 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Declined.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Declined.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Declined.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Declined.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Device-code.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Device-code.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Device-code.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Device-code.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Device-not-signed-in.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Device-not-signed-in.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Device-not-signed-in.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Device-not-signed-in.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Device-not-supported.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Device-not-supported.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Device-not-supported.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Device-not-supported.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Expired.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Expired.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Expired.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Expired.png 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 new file mode 100644 index 0000000000..8125801fb4 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Initial.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c418665989dab2f2a2ccc3ccce1293dc2da665f2bf14a34f931da866e4cc11db +size 83528 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Invalid.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Invalid.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Invalid.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Invalid.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Linking-unsupported.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Linking-unsupported.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Linking-unsupported.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Linking-unsupported.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.No-Camera-Permission.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.No-Camera-Permission.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.No-Camera-Permission.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.No-Camera-Permission.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Scanning.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Scanning.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Scanning.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Scanning.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Unknown-error.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Unknown-error.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Unknown-error.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Unknown-error.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Verification-code.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Verification-code.png new file mode 100644 index 0000000000..dbebf00358 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Verification-code.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:404e142dc91d14a2cff281674cfa7b2b288f92e484a4a2d81f613d44952aea97 +size 70641 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Cancelled.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Cancelled.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Cancelled.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Cancelled.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Connecting.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Connecting.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Connecting.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Connecting.png 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 new file mode 100644 index 0000000000..dc453e6f24 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Connection-not-secure.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:726da5e97cf060ea185394aa68ae1c7c438186662efae37bba2765e49aa64691 +size 163975 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Declined.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Declined.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Declined.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Declined.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Device-code.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Device-code.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Device-code.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Device-code.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Device-not-signed-in.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Device-not-signed-in.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Device-not-signed-in.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Device-not-signed-in.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Device-not-supported.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Device-not-supported.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Device-not-supported.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Device-not-supported.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Expired.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Expired.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Expired.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Expired.png 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 new file mode 100644 index 0000000000..eee39bbea8 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Initial.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:73f83bfca996f596775273e3ee56558e093674e98ba37ce0006c04c82d1a5b0d +size 116625 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Invalid.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Invalid.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Invalid.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Invalid.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Linking-unsupported.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Linking-unsupported.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Linking-unsupported.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Linking-unsupported.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.No-Camera-Permission.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.No-Camera-Permission.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.No-Camera-Permission.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.No-Camera-Permission.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Scanning.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Scanning.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Scanning.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Scanning.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Unknown-error.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Unknown-error.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Unknown-error.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Unknown-error.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Verification-code.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Verification-code.png new file mode 100644 index 0000000000..9375dd0bd1 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Verification-code.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:382c71c5c3f52f3011cf1b820212f3f60275824bed1de9c1d276732db5d9259f +size 93276 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPad-en-GB.1.png new file mode 100644 index 0000000000..4973c50d8f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b1421a726565df2dad3ab8f0febd352f23489ac4ca583905740ffffeb5931660 +size 157682 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPad-pseudo.1.png new file mode 100644 index 0000000000..1d0d0f5784 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:28768fa226f7387ef2e1c257364af742d0b201c3b1e2200d5bf9c5b6cd7a5ede +size 158659 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..d24f5b46fb --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e4ee2d0a1b36a89d157d405a42124c399b48b6d63ecad48c8e529532e7a61fa +size 65270 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..4ea8d217d5 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2a6a9a8bd8535ba80b94570c01e299999dd63d268e55b30e76edade00316d606 +size 65983 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-en-GB.Loading-Member.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-en-GB.Loading-Member.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-en-GB.Loading-Member.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-en-GB.Loading-Member.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-en-GB.No-Image.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-en-GB.No-Image.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-en-GB.No-Image.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-en-GB.No-Image.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-en-GB.With-Image.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-en-GB.With-Image.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-en-GB.With-Image.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-en-GB.With-Image.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-pseudo.Loading-Member.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-pseudo.Loading-Member.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-pseudo.Loading-Member.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-pseudo.Loading-Member.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-pseudo.No-Image.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-pseudo.No-Image.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-pseudo.No-Image.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-pseudo.No-Image.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-pseudo.With-Image.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-pseudo.With-Image.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-pseudo.With-Image.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-pseudo.With-Image.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-15-en-GB.Loading-Member.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-16-en-GB.Loading-Member.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-15-en-GB.Loading-Member.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-16-en-GB.Loading-Member.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-15-en-GB.No-Image.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-16-en-GB.No-Image.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-15-en-GB.No-Image.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-16-en-GB.No-Image.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-15-en-GB.With-Image.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-16-en-GB.With-Image.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-15-en-GB.With-Image.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-16-en-GB.With-Image.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-15-pseudo.Loading-Member.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-16-pseudo.Loading-Member.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-15-pseudo.Loading-Member.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-16-pseudo.Loading-Member.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-15-pseudo.No-Image.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-16-pseudo.No-Image.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-15-pseudo.No-Image.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-16-pseudo.No-Image.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-15-pseudo.With-Image.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-16-pseudo.With-Image.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-15-pseudo.With-Image.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-16-pseudo.With-Image.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPhone-16-pseudo.1.png 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 new file mode 100644 index 0000000000..91723317e9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f232c3e6380680ee984f9aab0dea0c81ed730abd9822a174f36a25e56b5d36ad +size 123079 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..9b69e8ae1c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f0ba1eecf3a7a4e2a0b9629292a07095640901001c714a87120735d9420dd3c +size 144852 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 new file mode 100644 index 0000000000..0264bbf24c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d740cb882db2bb28a58d230ddbecb05e5137ed90599b548d0c738a41c0328627 +size 76955 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 new file mode 100644 index 0000000000..c6a952c1e4 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d7c5eb70787cf15781d04f624de54f40214f069f02ae148006c34a492c333ac +size 108915 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPad-en-GB.Identity-Changed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPad-en-GB.Identity-Changed.png new file mode 100644 index 0000000000..2063294306 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPad-en-GB.Identity-Changed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e4f2a9579f5e64da486ac22e56f1cea10f3450687641900790408f9f3004311 +size 121955 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPad-en-GB.Own-Unsigned-Device.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPad-en-GB.Own-Unsigned-Device.png new file mode 100644 index 0000000000..7426febed3 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPad-en-GB.Own-Unsigned-Device.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4753c2858ee5ecec25a29b399e7ea80182f687c6a2f841a92a414e8e920b5924 +size 125882 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPad-en-GB.Unsigned-Device.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPad-en-GB.Unsigned-Device.png new file mode 100644 index 0000000000..da16c72328 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPad-en-GB.Unsigned-Device.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89391abf747aef94c9b315e19607fd4256956d269d2f53141477952e604e8d24 +size 123919 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPad-pseudo.Identity-Changed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPad-pseudo.Identity-Changed.png new file mode 100644 index 0000000000..343d5fa491 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPad-pseudo.Identity-Changed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ec75d1ba7375877c82ea1b71947607558762aa00ae4ca575bcc81a8434e9b76b +size 155316 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPad-pseudo.Own-Unsigned-Device.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPad-pseudo.Own-Unsigned-Device.png new file mode 100644 index 0000000000..824c7dd49b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPad-pseudo.Own-Unsigned-Device.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a2d8fb744f1ae503247c5da24b629808edef82b99478834a31f4116d7d5db992 +size 160093 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPad-pseudo.Unsigned-Device.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPad-pseudo.Unsigned-Device.png new file mode 100644 index 0000000000..a618927ca0 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPad-pseudo.Unsigned-Device.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f58a9af3a9780ad49b7b5a90fa393b8f69bc1c752713477cbfb574389d101840 +size 159142 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPhone-16-en-GB.Identity-Changed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPhone-16-en-GB.Identity-Changed.png new file mode 100644 index 0000000000..3108ccc31f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPhone-16-en-GB.Identity-Changed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ca3e0c570345f63fe2d0e915b9cb1c68faa5758acf87901b21b674a9838b380 +size 85398 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPhone-16-en-GB.Own-Unsigned-Device.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPhone-16-en-GB.Own-Unsigned-Device.png new file mode 100644 index 0000000000..f508950f32 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPhone-16-en-GB.Own-Unsigned-Device.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5145981b3a4ec6e66341f81fd7dac4c6229f361c22f2ceb9a2f3b442cecaec76 +size 90320 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPhone-16-en-GB.Unsigned-Device.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPhone-16-en-GB.Unsigned-Device.png new file mode 100644 index 0000000000..55ad8a9b96 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPhone-16-en-GB.Unsigned-Device.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c37c7425834dd88af07803bf1a414cfc6155957874cd2fe5a09fd6e17ff5458b +size 88086 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPhone-16-pseudo.Identity-Changed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPhone-16-pseudo.Identity-Changed.png new file mode 100644 index 0000000000..947b01f288 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPhone-16-pseudo.Identity-Changed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb7f1eb81810906391eb771ffcec9f37357d2f340677e151edbe1b7977477137 +size 128891 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPhone-16-pseudo.Own-Unsigned-Device.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPhone-16-pseudo.Own-Unsigned-Device.png new file mode 100644 index 0000000000..0104d2f507 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPhone-16-pseudo.Own-Unsigned-Device.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88602e805a91c4857f0f8101d1dd0856d92b8d3ba1335d2057e1e3cec727ec6b +size 137841 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPhone-16-pseudo.Unsigned-Device.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPhone-16-pseudo.Unsigned-Device.png new file mode 100644 index 0000000000..b7a343a636 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_resolveVerifiedUserSendFailureScreen-iPhone-16-pseudo.Unsigned-Device.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:63fbe1cf5d4c4b23b1f6fbe2b33d41c0d74654ccd33a473fd71527b7aa75a921 +size 134230 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomAttachmentPicker-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAttachmentPicker-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomAttachmentPicker-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAttachmentPicker-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomAttachmentPicker-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAttachmentPicker-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomAttachmentPicker-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAttachmentPicker-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomAttachmentPicker-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAttachmentPicker-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomAttachmentPicker-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAttachmentPicker-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomAttachmentPicker-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAttachmentPicker-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomAttachmentPicker-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAttachmentPicker-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomAvatarImage-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomAvatarImage-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomAvatarImage-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomAvatarImage-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomAvatarImage-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomAvatarImage-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomAvatarImage-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomAvatarImage-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPhone-16-pseudo.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-en-GB.Member-moderation.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-en-GB.Member-moderation.png new file mode 100644 index 0000000000..333dd906f2 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-en-GB.Member-moderation.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:baacb9057ff518db7af67439e7fc89debf425599c19c209a131996c40e1ae359 +size 133463 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-en-GB.Messages-and-Content.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-en-GB.Messages-and-Content.png new file mode 100644 index 0000000000..894cadfce0 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-en-GB.Messages-and-Content.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:46ec065c952eb4e3afc3af7ce8ee345b93aacab3700153a76fed43a7c8782b66 +size 120238 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-en-GB.Room-details.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-en-GB.Room-details.png new file mode 100644 index 0000000000..3cd424cbb3 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-en-GB.Room-details.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c2154f032a8ffbcbac33f69832671055bb13637232ea12bcfb09b554bb95c398 +size 138563 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-pseudo.Member-moderation.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-pseudo.Member-moderation.png new file mode 100644 index 0000000000..4555c20fce --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-pseudo.Member-moderation.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d97086fdd2914b42f6e70a1741fe1cadf29e151db976128e2371a3e4b1502a6a +size 144048 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-pseudo.Messages-and-Content.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-pseudo.Messages-and-Content.png new file mode 100644 index 0000000000..2e37e27917 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-pseudo.Messages-and-Content.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c5a11b430c30cc17b69c340f5fcd4cd35c49c47c02927bb54a6fd6b406c18bf +size 128074 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-pseudo.Room-details.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-pseudo.Room-details.png new file mode 100644 index 0000000000..4be88b0c72 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-pseudo.Room-details.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:974117a157ffc697c369902c6e4b7ca37de6f78638e14c64449dcdb73b22d62c +size 153671 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-16-en-GB.Member-moderation.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-16-en-GB.Member-moderation.png new file mode 100644 index 0000000000..6977fc0a90 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-16-en-GB.Member-moderation.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9334d0273bfd78a7ec5e75067eba45ae443cba83f58859cbffbc02c7a3a2a39e +size 80837 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-16-en-GB.Messages-and-Content.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-16-en-GB.Messages-and-Content.png new file mode 100644 index 0000000000..d7871da462 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-16-en-GB.Messages-and-Content.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a4715abe6c09498294ba2e7a413a080809f166ef0da42c5bd3be2deb1dd1ab11 +size 69489 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-16-en-GB.Room-details.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-16-en-GB.Room-details.png new file mode 100644 index 0000000000..4dda036f2f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-16-en-GB.Room-details.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e42a536d87d54d944c68a97f3c845d8d978055aaf684c523c431caf951119bdd +size 85586 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-16-pseudo.Member-moderation.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-16-pseudo.Member-moderation.png new file mode 100644 index 0000000000..5661958632 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-16-pseudo.Member-moderation.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:97839dd8b0691ee4c806d8e08d856f81d05edc9da5a36c784d06685f89efe53a +size 101917 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-16-pseudo.Messages-and-Content.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-16-pseudo.Messages-and-Content.png new file mode 100644 index 0000000000..f1990cc897 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-16-pseudo.Messages-and-Content.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e1abea40f4acc7eb23e4ba5d926f61de3c0e8a332bd561e85f1f8ed6cf45f0e5 +size 84127 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-16-pseudo.Room-details.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-16-pseudo.Room-details.png new file mode 100644 index 0000000000..ab624c0c06 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-16-pseudo.Room-details.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a599243be1587e7eba59e715827ffb50f4fd669af4be8c81d8b210a45f5e3976 +size 107742 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 new file mode 100644 index 0000000000..198ec0bb23 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-en-GB.Administrators.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:988cea50144bdf8d69d6d1e3b973e2dabe4cb063b1d8b2b7c66eab31aaf17a98 +size 189938 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 new file mode 100644 index 0000000000..3a284c366a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-en-GB.Moderators.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:697e1ccf98b419d86cec1a7cca617be7ef9308822756356713a9e840118e19ea +size 175223 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-pseudo.Administrators.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-pseudo.Administrators.png new file mode 100644 index 0000000000..3af17f8ef8 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-pseudo.Administrators.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f063d70cd89c19be28f7069000d536be933b759f39c87a15bf3fc88246c1570f +size 196100 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-pseudo.Moderators.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-pseudo.Moderators.png new file mode 100644 index 0000000000..a1f7e413bc --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-pseudo.Moderators.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a8122c0fb9778e3a3478e820b354844249e68d70562232a57e349242a86d3de7 +size 185772 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 new file mode 100644 index 0000000000..0eb1288bdb --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-16-en-GB.Administrators.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:72dd7af6ed995597f92399822ea9469af8a6cc68a591090a19b8985533d24deb +size 141580 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 new file mode 100644 index 0000000000..b1534c7bb8 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-16-en-GB.Moderators.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7f39f2a11a561eabe2fe13409b346888df86b0e10d4786557f66afa7048bc239 +size 129716 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 new file mode 100644 index 0000000000..6e05223bef --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-16-pseudo.Administrators.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f023a7cbc6e069115c0749d0dff3f10ae86f67c785676cc53975416e534e1d9 +size 147174 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 new file mode 100644 index 0000000000..458dcd036c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-16-pseudo.Moderators.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d822b8c18fc4b1c68f429504831f9305eed9fcebcced9c8f708a309f652db59 +size 138913 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreenRow-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenRow-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreenRow-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenRow-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreenRow-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenRow-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreenRow-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenRow-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreenRow-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenRow-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreenRow-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenRow-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreenRow-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenRow-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreenRow-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenRow-iPhone-16-pseudo.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPad-en-GB.1.png new file mode 100644 index 0000000000..03a56f287b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c0e0d75e303823aa3bd0472770f17ce79f112b7d2eb36f94652155692fbcc115 +size 46050 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPad-pseudo.1.png new file mode 100644 index 0000000000..03a56f287b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c0e0d75e303823aa3bd0472770f17ce79f112b7d2eb36f94652155692fbcc115 +size 46050 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..896a10fa34 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a06657c9c3bd5b4dc8f3aff47b7e6cf6dba39590087ccf8a568929fba34a95f9 +size 36376 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..896a10fa34 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a06657c9c3bd5b4dc8f3aff47b7e6cf6dba39590087ccf8a568929fba34a95f9 +size 36376 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 new file mode 100644 index 0000000000..8cf9f1de84 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-en-GB.Editable.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a86f66b790b99c27ef11be576c3d93d28263aac0660fd18c27066483dcbc7ae +size 104864 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-en-GB.Read-only.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-en-GB.Read-only.png new file mode 100644 index 0000000000..0ecbcda245 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-en-GB.Read-only.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e2271cb9811ad772b2df2f3ca4a97d9f2784611dafc321940aca7c429366afef +size 96768 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-pseudo.Editable.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-pseudo.Editable.png new file mode 100644 index 0000000000..07bd24bef6 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-pseudo.Editable.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d98a0fdde21dd983e2423f291c87facecbd98e2e026576ba23152eeebd483d20 +size 109406 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-pseudo.Read-only.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-pseudo.Read-only.png new file mode 100644 index 0000000000..bd5c8656d3 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-pseudo.Read-only.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:31ed52c18db7e47916626fb03bbcb046cbb5d0f3d7be58c2f7b5fa34f9a6105b +size 100393 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 new file mode 100644 index 0000000000..2c10803442 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-en-GB.Editable.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aab4eda3890d79da42a2945387ea8f7ff046643d5e8e0b1d17275814ad284183 +size 57794 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-en-GB.Read-only.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-en-GB.Read-only.png new file mode 100644 index 0000000000..fba9f3fc4f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-en-GB.Read-only.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1561c8ac533cc7a6910815613ab49ad1d5d757088a31c612044421157738523a +size 48986 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 new file mode 100644 index 0000000000..035d621a30 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-pseudo.Editable.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:651a9dae5da28d6b42de24f1f9154c8f5bad7c0bc88f3fd924a489d6f6ba9bc2 +size 67616 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-pseudo.Read-only.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-pseudo.Read-only.png new file mode 100644 index 0000000000..998523a718 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-pseudo.Read-only.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f7d60be0ec99441733d880a7d28f830096bc2ca3e5f06d5803d5faaec35a8189 +size 53661 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.DM-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.DM-Room.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.DM-Room.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.DM-Room.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.Generic-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.Generic-Room.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.Generic-Room.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.Generic-Room.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.Simple-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.Simple-Room.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.Simple-Room.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.Simple-Room.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.DM-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.DM-Room.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.DM-Room.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.DM-Room.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.Generic-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.Generic-Room.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.Generic-Room.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.Generic-Room.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.Simple-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.Simple-Room.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.Simple-Room.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.Simple-Room.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-15-en-GB.DM-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-en-GB.DM-Room.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-15-en-GB.DM-Room.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-en-GB.DM-Room.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-15-en-GB.Generic-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-en-GB.Generic-Room.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-15-en-GB.Generic-Room.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-en-GB.Generic-Room.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-15-en-GB.Simple-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-en-GB.Simple-Room.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-15-en-GB.Simple-Room.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-en-GB.Simple-Room.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-15-pseudo.DM-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-pseudo.DM-Room.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-15-pseudo.DM-Room.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-pseudo.DM-Room.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-15-pseudo.Generic-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-pseudo.Generic-Room.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-15-pseudo.Generic-Room.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-pseudo.Generic-Room.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-15-pseudo.Simple-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-pseudo.Simple-Room.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-15-pseudo.Simple-Room.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-pseudo.Simple-Room.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchCell-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchCell-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchCell-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchCell-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchCell-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchCell-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchCell-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchCell-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchCell-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchCell-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchCell-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchCell-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchCell-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchCell-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchCell-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchCell-iPhone-16-pseudo.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPad-en-GB.1.png new file mode 100644 index 0000000000..68337fae4a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:222b8e57adaf6d234c2e6ac026cba0380131c7085d6a4d0e15e6fb349dbea1d8 +size 93186 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..9fe58baf32 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1040add34f78fa95ae396d7ce95df29a7f03c73ade149a5d0efa9418335531a6 +size 95828 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..d0e1cc4330 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fdaf986c1521ecb43b117f3197053f589e66e3e496a51d824629d8253653a713 +size 49876 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..bd143b2b96 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4840a11a65bc0a611c5cb2b93883cf707f1cbd686359909704398ed87eced86d +size 52399 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDirectorySearchView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-en-GB.1.png new file mode 100644 index 0000000000..f00ad52876 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24e6713edd0b7d1d95b99351f5b9791ae8f7e049c155cbfc5e66a9e3b9f72606 +size 16308 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-en-GB.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-en-GB.2.png new file mode 100644 index 0000000000..08d6635efc --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-en-GB.2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94a649334de3e92c04c8c5fa24606ce4338b38867d3af71ba044ebc199bbf8d5 +size 11439 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-pseudo.1.png new file mode 100644 index 0000000000..f00ad52876 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24e6713edd0b7d1d95b99351f5b9791ae8f7e049c155cbfc5e66a9e3b9f72606 +size 16308 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-pseudo.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-pseudo.2.png new file mode 100644 index 0000000000..08d6635efc --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-pseudo.2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94a649334de3e92c04c8c5fa24606ce4338b38867d3af71ba044ebc199bbf8d5 +size 11439 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..03a71d210a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:22da22f2fe62f66dd68084f9590079e0630477697bed4913ebaee4568d7d3db8 +size 12472 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-16-en-GB.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-16-en-GB.2.png new file mode 100644 index 0000000000..7825f2956a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-16-en-GB.2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:07945ef1e674a1744a26d59745956b94201a9a2b0fdb9a1c15933c32ce246e89 +size 7886 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..03a71d210a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:22da22f2fe62f66dd68084f9590079e0630477697bed4913ebaee4568d7d3db8 +size 12472 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-16-pseudo.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-16-pseudo.2.png new file mode 100644 index 0000000000..7825f2956a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-16-pseudo.2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:07945ef1e674a1744a26d59745956b94201a9a2b0fdb9a1c15933c32ce246e89 +size 7886 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomInviterLabel-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomInviterLabel-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomInviterLabel-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomInviterLabel-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomInviterLabel-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomInviterLabel-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomInviterLabel-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomInviterLabel-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFilterView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFilterView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView-iPad-en-GB.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFilterView-iPad-en-GB.2.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView-iPad-en-GB.2.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFilterView-iPad-en-GB.2.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFilterView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFilterView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView-iPad-pseudo.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFilterView-iPad-pseudo.2.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView-iPad-pseudo.2.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFilterView-iPad-pseudo.2.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFilterView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFilterView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView-iPhone-15-en-GB.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFilterView-iPhone-16-en-GB.2.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView-iPhone-15-en-GB.2.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFilterView-iPhone-16-en-GB.2.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFilterView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFilterView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView-iPhone-15-pseudo.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFilterView-iPhone-16-pseudo.2.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView-iPhone-15-pseudo.2.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFilterView-iPhone-16-pseudo.2.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersView-iPad-en-GB.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersView-iPad-en-GB.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersView-iPad-en-GB.2.png new file mode 100644 index 0000000000..7b30981719 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersView-iPad-en-GB.2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a5fd46a399d6e4f925004ca1ddaac8f5b4178783f56966a93a292b51c198f3b4 +size 79597 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersView-iPad-pseudo.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersView-iPad-pseudo.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersView-iPad-pseudo.2.png new file mode 100644 index 0000000000..b63a16d5e2 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersView-iPad-pseudo.2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ce9aded8dd8cc2efe4261577d391057c04d28343230f5d4cdb84723c0816240 +size 80946 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersView-iPhone-16-en-GB.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersView-iPhone-16-en-GB.2.png new file mode 100644 index 0000000000..751518bc67 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersView-iPhone-16-en-GB.2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1e9a2b76583c8a9725cfc154955cbd88e178664294152aebc82f39dddba4d638 +size 38460 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersView-iPhone-16-pseudo.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersView-iPhone-16-pseudo.2.png new file mode 100644 index 0000000000..b1e1ddf5fe --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersView-iPhone-16-pseudo.2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8b1bf5c8b6e2f4335a3d222e5e251edd48b97be4ba2f467d5b54bcf8c88753bc +size 34985 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-en-GB.Account-Owner.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-en-GB.Account-Owner.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-en-GB.Account-Owner.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-en-GB.Account-Owner.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-en-GB.Ignored-User.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-en-GB.Ignored-User.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-en-GB.Ignored-User.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-en-GB.Ignored-User.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-en-GB.Other-User.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-en-GB.Other-User.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-en-GB.Other-User.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-en-GB.Other-User.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-pseudo.Account-Owner.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-pseudo.Account-Owner.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-pseudo.Account-Owner.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-pseudo.Account-Owner.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-pseudo.Ignored-User.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-pseudo.Ignored-User.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-pseudo.Ignored-User.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-pseudo.Ignored-User.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-pseudo.Other-User.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-pseudo.Other-User.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-pseudo.Other-User.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-pseudo.Other-User.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-15-en-GB.Account-Owner.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-en-GB.Account-Owner.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-15-en-GB.Account-Owner.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-en-GB.Account-Owner.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-15-en-GB.Ignored-User.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-en-GB.Ignored-User.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-15-en-GB.Ignored-User.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-en-GB.Ignored-User.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-15-en-GB.Other-User.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-en-GB.Other-User.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-15-en-GB.Other-User.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-en-GB.Other-User.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-15-pseudo.Account-Owner.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-pseudo.Account-Owner.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-15-pseudo.Account-Owner.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-pseudo.Account-Owner.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-15-pseudo.Ignored-User.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-pseudo.Ignored-User.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-15-pseudo.Ignored-User.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-pseudo.Ignored-User.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-15-pseudo.Other-User.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-pseudo.Other-User.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-15-pseudo.Other-User.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-pseudo.Other-User.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-en-GB.Banned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-en-GB.Banned.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-en-GB.Banned.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-en-GB.Banned.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-en-GB.Joined.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-en-GB.Joined.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-en-GB.Joined.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-en-GB.Joined.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-pseudo.Banned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-pseudo.Banned.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-pseudo.Banned.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-pseudo.Banned.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-pseudo.Joined.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-pseudo.Joined.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-pseudo.Joined.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-pseudo.Joined.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-15-en-GB.Banned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-16-en-GB.Banned.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-15-en-GB.Banned.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-16-en-GB.Banned.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-15-en-GB.Joined.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-16-en-GB.Joined.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-15-en-GB.Joined.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-16-en-GB.Joined.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-15-pseudo.Banned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-16-pseudo.Banned.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-15-pseudo.Banned.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-16-pseudo.Banned.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-15-pseudo.Joined.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-16-pseudo.Joined.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-15-pseudo.Joined.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-16-pseudo.Joined.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPad-en-GB.1.png new file mode 100644 index 0000000000..cc1a252627 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:856c6765b1b094095b58ff420287e53da9c0c4b81223ad1626d210318b8d1612 +size 157536 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPad-pseudo.1.png new file mode 100644 index 0000000000..f1cf44e9ff --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:de681676b70315efa05d12f627df09cd46475e72803636f9999606ca6ab90276 +size 161285 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..8e50ef6050 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa2bce323be5587c82db9e4939d7e8c71ae2c372aef069f5a924f93137375d23 +size 103394 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..8e275e596a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c826f78606eaaedb7e4d91e91f35cd615afb856820bd138fff37657e8ecf4728 +size 107798 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 new file mode 100644 index 0000000000..3983942497 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Banned.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6f5ed0c823ac1281ccdb4bcfa28ca9dd3f8d1f99a19d3eb0ff8458e865ea8e4a +size 116814 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 new file mode 100644 index 0000000000..8628ed74fb --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Empty-Banned.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5bfce5d9c391d24879f2085a58816ff539c87ecc63c0226d1fd41e28227b5d70 +size 92229 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 new file mode 100644 index 0000000000..513043deb7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Members.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2b8e47d918ee9a42fce8d46ba5a8a7f4a5ffc8129f55a76a6061f3f8642b0246 +size 132835 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 new file mode 100644 index 0000000000..2545e36c02 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Invites.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d9509b45509af3fb2f67033b37d93c2c357d6728640d297d5b5a4532d4ba9cf1 +size 136138 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 new file mode 100644 index 0000000000..fadaf93815 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Member.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d964c7a297796f7df990fbdf40dd460f6486ddb604edccd17a59ac7561ca2c3f +size 125525 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 new file mode 100644 index 0000000000..b35f188683 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Banned.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:280ae20f285959f0b80c3c1a8493246733b6e4dfa1cad10aafbf70d5317e669d +size 121457 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 new file mode 100644 index 0000000000..b41282300b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Empty-Banned.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5a43d08d3ab0cffcee1e6fb1f119af93d1bcd75f5e57563192abdb22d0ce3830 +size 100570 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 new file mode 100644 index 0000000000..115d039f64 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Members.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:80cfd43759ae038e93fb7bdc0754f4030e8c8bc364897b9420d3e92cfebfbf32 +size 141768 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Invites.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Invites.png new file mode 100644 index 0000000000..abcbc8b24c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Invites.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3f8c8a3e0ad9b78832c0492cc95424018fea10c3b4726c8ab2bf657df47089d6 +size 144306 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Member.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Member.png new file mode 100644 index 0000000000..31dc165a82 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Member.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:479f6184c518caa0337a2605293dd1307e5cee839727c7adc2e64dfeddba0e8b +size 133441 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 new file mode 100644 index 0000000000..6c320b9828 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Admin-Banned.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6f9871ae3306a42d01602c7a8cc2153131c1bd9c91f13129c3bdf0d8ece816c6 +size 68400 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 new file mode 100644 index 0000000000..fb947d7f96 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Admin-Empty-Banned.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0a96b9608b3fbdef660995e45324eb1c5b5cbdf18cae679f17cded799aa9d1c9 +size 48922 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 new file mode 100644 index 0000000000..352123acf0 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Admin-Members.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:58820cced75f459149aa85f2b32ddc9f6311fcb0795c5e8801b45c228751d698 +size 83703 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 new file mode 100644 index 0000000000..0d7dfda678 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Invites.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b022726222227a8f90998e54d58bcd7ab666089d1d7dff2724f21b11daf2b554 +size 86214 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 new file mode 100644 index 0000000000..9c92bf724b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Member.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f7925fd0beeac60deea2db678b17265aedee906252d97d0214f641c2a21bf5fb +size 37037 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 new file mode 100644 index 0000000000..a44ac201be --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Admin-Banned.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:de46b50e23ecb747e9d60c9448b60a977571af8e74ce4f5ca20e440189ce36f7 +size 73574 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 new file mode 100644 index 0000000000..4bacc94c2d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Admin-Empty-Banned.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d8830e48e24781b958a21e9ce56ac7f12583cf237fc4a40cff57a4a8fb4e5e2 +size 59454 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 new file mode 100644 index 0000000000..e76a1aec2e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Admin-Members.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:54a2cde62d75459851c485b761aa5161cbb4176560eeaab69fcfa520e362bb11 +size 93420 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 new file mode 100644 index 0000000000..6de78ba4b3 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Invites.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f4853074c004e451d4d88453b977064c25b59a29803acb1ea5b38882c7860ad3 +size 96319 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 new file mode 100644 index 0000000000..2b199a18e0 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Member.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4758385db96e9d880f7ff670f1b312964b27910ba1c55ecafa9a451c964ab474 +size 40619 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPad-en-GB.Encrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPad-en-GB.Encrypted.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPad-en-GB.Encrypted.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPad-en-GB.Encrypted.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPad-en-GB.Unencrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPad-en-GB.Unencrypted.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPad-en-GB.Unencrypted.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPad-en-GB.Unencrypted.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPad-pseudo.Encrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPad-pseudo.Encrypted.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPad-pseudo.Encrypted.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPad-pseudo.Encrypted.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPad-pseudo.Unencrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPad-pseudo.Unencrypted.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPad-pseudo.Unencrypted.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPad-pseudo.Unencrypted.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPhone-15-en-GB.Encrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPhone-16-en-GB.Encrypted.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPhone-15-en-GB.Encrypted.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPhone-16-en-GB.Encrypted.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPhone-15-en-GB.Unencrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPhone-16-en-GB.Unencrypted.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPhone-15-en-GB.Unencrypted.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPhone-16-en-GB.Unencrypted.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPhone-15-pseudo.Encrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPhone-16-pseudo.Encrypted.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPhone-15-pseudo.Encrypted.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPhone-16-pseudo.Encrypted.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPhone-15-pseudo.Unencrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPhone-16-pseudo.Unencrypted.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPhone-15-pseudo.Unencrypted.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsCustomSectionView-iPhone-16-pseudo.Unencrypted.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPad-en-GB.Custom.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPad-en-GB.Custom.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPad-en-GB.Custom.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPad-en-GB.Custom.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPad-en-GB.Default.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPad-en-GB.Default.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPad-en-GB.Default.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPad-en-GB.Default.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPad-pseudo.Custom.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPad-pseudo.Custom.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPad-pseudo.Custom.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPad-pseudo.Custom.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPad-pseudo.Default.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPad-pseudo.Default.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPad-pseudo.Default.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPad-pseudo.Default.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPhone-15-en-GB.Custom.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPhone-16-en-GB.Custom.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPhone-15-en-GB.Custom.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPhone-16-en-GB.Custom.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPhone-15-en-GB.Default.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPhone-16-en-GB.Default.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPhone-15-en-GB.Default.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPhone-16-en-GB.Default.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPhone-15-pseudo.Custom.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPhone-16-pseudo.Custom.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPhone-15-pseudo.Custom.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPhone-16-pseudo.Custom.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPhone-15-pseudo.Default.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPhone-16-pseudo.Default.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPhone-15-pseudo.Default.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsScreen-iPhone-16-pseudo.Default.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPad-en-GB.Encrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPad-en-GB.Encrypted.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPad-en-GB.Encrypted.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPad-en-GB.Encrypted.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPad-en-GB.Unencrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPad-en-GB.Unencrypted.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPad-en-GB.Unencrypted.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPad-en-GB.Unencrypted.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPad-pseudo.Encrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPad-pseudo.Encrypted.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPad-pseudo.Encrypted.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPad-pseudo.Encrypted.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPad-pseudo.Unencrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPad-pseudo.Unencrypted.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPad-pseudo.Unencrypted.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPad-pseudo.Unencrypted.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPhone-15-en-GB.Encrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPhone-16-en-GB.Encrypted.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPhone-15-en-GB.Encrypted.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPhone-16-en-GB.Encrypted.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPhone-15-en-GB.Unencrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPhone-16-en-GB.Unencrypted.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPhone-15-en-GB.Unencrypted.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPhone-16-en-GB.Unencrypted.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPhone-15-pseudo.Encrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPhone-16-pseudo.Encrypted.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPhone-15-pseudo.Encrypted.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPhone-16-pseudo.Encrypted.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPhone-15-pseudo.Unencrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPhone-16-pseudo.Unencrypted.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPhone-15-pseudo.Unencrypted.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomNotificationSettingsUserDefinedScreen-iPhone-16-pseudo.Unencrypted.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-en-GB.No-polls.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-en-GB.No-polls.png new file mode 100644 index 0000000000..10cd5de873 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-en-GB.No-polls.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:650ee52b5e515c784ef1017a7d70905487fe7778491d0495e247613319e36cb2 +size 97341 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-en-GB.polls.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-en-GB.polls.png new file mode 100644 index 0000000000..46e4761f9f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-en-GB.polls.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3263575d05d09fe3ce6a16d02d6bbb4e4276688527311b893d8eac72589c33e3 +size 190165 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-pseudo.No-polls.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-pseudo.No-polls.png new file mode 100644 index 0000000000..dcdc6e5c87 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-pseudo.No-polls.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:734698e96823c3b2f52749b0efc8cd35df46dbd087a26e8d6beeb9d453b6490d +size 101511 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-pseudo.polls.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-pseudo.polls.png new file mode 100644 index 0000000000..e2f89b57df --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-pseudo.polls.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bf48111a5d231aba54ecfc1f935fc07c5993945bc02fe823c174f01e11111b11 +size 218567 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-16-en-GB.No-polls.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-16-en-GB.No-polls.png new file mode 100644 index 0000000000..3714979731 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-16-en-GB.No-polls.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:02d61323b3873b6fcf72bde1d0fdb53087654dfc59ef4ebe733a249b916ba6ab +size 50362 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-16-en-GB.polls.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-16-en-GB.polls.png new file mode 100644 index 0000000000..1201b27f4e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-16-en-GB.polls.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:323b0997a1c95367147785ea9e84119605d63ed71437021993b571672f25f906 +size 119176 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-16-pseudo.No-polls.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-16-pseudo.No-polls.png new file mode 100644 index 0000000000..1868d0d954 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-16-pseudo.No-polls.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fc44e2105daba0ad118dfe7b060e2e815ed2fdb0059f8d66f200ba115f44048e +size 58545 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-16-pseudo.polls.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-16-pseudo.polls.png new file mode 100644 index 0000000000..e2a9bc382f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-16-pseudo.polls.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:91c0d9ba97db9ca4446a07665f47a29982d8c904a80e07e4ca8cd448ebbcc48d +size 145040 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPad-en-GB.1.png new file mode 100644 index 0000000000..1158d2a745 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd81fe87f101c6954bba7ba2b72d428d8d41fa0fb157dc94e0350c3f69029a96 +size 133828 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..2c12736833 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8067249f4f4af57e5756635dcaf8ab4770735cfe4299149ead5211f83c7b2b13 +size 142507 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..5378181385 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c76c19609c135d52ad6f1a80cdf079496140d1feab6ac11c60fca54bf132e003 +size 83433 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..4ec7d91a00 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1ee34fcae6f73f3dd55b9cdf4c071fbc271f09cb8932e1c9e471e50ef3c1f447 +size 100576 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 new file mode 100644 index 0000000000..16e7cc7bbc --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dbba95d7bded549e3b54dd8468f44f338f75df9dc2d384c800ca69d240c526bb +size 295572 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..74310722a3 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0d28a596ca48a0cd680be7014adef2f2aac11aaf1592676da57b942bd3329708 +size 297527 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 new file mode 100644 index 0000000000..e044e0e64d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fbfaf40b0602964736bbe6dc41beea21d1733c8ec0b84c82e0c547596c4032f0 +size 180515 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 new file mode 100644 index 0000000000..f8a53763cf --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c928084fecfee3ff804ebc41d17b3433fe7dea94f7c0c82ef7c40175203061f +size 178534 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 new file mode 100644 index 0000000000..97e45286c5 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cd5e118a74f0842e64539d604b995641aab413de29620c1e5480ea4fb778f1b4 +size 66806 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPad-pseudo.1.png new file mode 100644 index 0000000000..97e45286c5 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cd5e118a74f0842e64539d604b995641aab413de29620c1e5480ea4fb778f1b4 +size 66806 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 new file mode 100644 index 0000000000..bebcfee580 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b0e9118102591b2d3279204dc35d37e465cb2dcd37d523754ac4b4b8123e0367 +size 43491 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 new file mode 100644 index 0000000000..bebcfee580 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b0e9118102591b2d3279204dc35d37e465cb2dcd37d523754ac4b4b8123e0367 +size 43491 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupKeyBackupScreen-iPad-en-GB.Set-up.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupKeyBackupScreen-iPad-en-GB.Set-up.png new file mode 100644 index 0000000000..c5b2362eee --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupKeyBackupScreen-iPad-en-GB.Set-up.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a643050cc5942ee578339ebadb7866dbb40bf8f7562f23ab4153713c9c2a0ec4 +size 133317 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupKeyBackupScreen-iPad-pseudo.Set-up.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupKeyBackupScreen-iPad-pseudo.Set-up.png new file mode 100644 index 0000000000..49e9d4252b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupKeyBackupScreen-iPad-pseudo.Set-up.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:854f870b886503f284b57f1504cc10c4d9b26314330858b11f5a6b4c039ff5ae +size 179519 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupKeyBackupScreen-iPhone-15-en-GB.Set-up.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupKeyBackupScreen-iPhone-16-en-GB.Set-up.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_secureBackupKeyBackupScreen-iPhone-15-en-GB.Set-up.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupKeyBackupScreen-iPhone-16-en-GB.Set-up.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupKeyBackupScreen-iPhone-15-pseudo.Set-up.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupKeyBackupScreen-iPhone-16-pseudo.Set-up.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_secureBackupKeyBackupScreen-iPhone-15-pseudo.Set-up.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupKeyBackupScreen-iPhone-16-pseudo.Set-up.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupLogoutConfirmationScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupLogoutConfirmationScreen-iPad-en-GB.1.png new file mode 100644 index 0000000000..b28f51195d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupLogoutConfirmationScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e916834a4e2dbf63997253df785d6f3fd450236394f59a0e07ff9b53e8cafd40 +size 111869 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupLogoutConfirmationScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupLogoutConfirmationScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..607012dd62 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupLogoutConfirmationScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5db371edb4cfc7927da9fa0c8c538290de10ac459b689a601d91ef1a4f5e1f5a +size 133384 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupLogoutConfirmationScreen-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupLogoutConfirmationScreen-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_secureBackupLogoutConfirmationScreen-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupLogoutConfirmationScreen-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupLogoutConfirmationScreen-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupLogoutConfirmationScreen-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_secureBackupLogoutConfirmationScreen-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupLogoutConfirmationScreen-iPhone-16-pseudo.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Incomplete.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Incomplete.png new file mode 100644 index 0000000000..f4524ff43a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Incomplete.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e8373d1d1b85980b3701f809b47e923ef15ca7091337ed2ba795e69325d9acb9 +size 113493 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Not-set-up.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Not-set-up.png new file mode 100644 index 0000000000..8a4b6adb8a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Not-set-up.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5b245cd8374447a696422108e5955dc9d426933652304a9fe1fe67bff356c682 +size 126623 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 new file mode 100644 index 0000000000..6c5e54e17f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Set-up.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5dbc11892838b9116bb678e1e824a6f4c72ac8ce1df97fb549befb83ebb9e925 +size 125669 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Unknown.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Unknown.png new file mode 100644 index 0000000000..d5c02e0299 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Unknown.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d69adc85173a9dd6bd318fec6c1a713af5d2026fc377b281a34c7a1b9becca1b +size 79419 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Incomplete.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Incomplete.png new file mode 100644 index 0000000000..8de933e4ec --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Incomplete.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f693c37838f16f111c8b5512658bf99ba0996bff89460cbb4a25d38cc308966 +size 130681 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Not-set-up.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Not-set-up.png new file mode 100644 index 0000000000..4968f59f46 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Not-set-up.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e837eaba5212626e18df37ff744cefc76ed03668a4e4ceea5f245f6c171bf440 +size 157836 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 new file mode 100644 index 0000000000..4354594c38 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Set-up.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5a757353f75f4489f6a9302bc200bb603dcf9e11944701485d0c90fd92554977 +size 152661 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Unknown.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Unknown.png new file mode 100644 index 0000000000..072bc09d94 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Unknown.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a18487a803b68bc729390c0dc924b562b564c148582c60dca9603f051ce3f0b3 +size 81568 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-15-en-GB.Incomplete.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-en-GB.Incomplete.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-15-en-GB.Incomplete.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-en-GB.Incomplete.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-15-en-GB.Not-set-up.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-en-GB.Not-set-up.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-15-en-GB.Not-set-up.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-en-GB.Not-set-up.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-15-en-GB.Set-up.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-en-GB.Set-up.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-15-en-GB.Set-up.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-en-GB.Set-up.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-15-en-GB.Unknown.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-en-GB.Unknown.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-15-en-GB.Unknown.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-en-GB.Unknown.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-15-pseudo.Incomplete.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-pseudo.Incomplete.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-15-pseudo.Incomplete.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-pseudo.Incomplete.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-15-pseudo.Not-set-up.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-pseudo.Not-set-up.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-15-pseudo.Not-set-up.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-pseudo.Not-set-up.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-15-pseudo.Set-up.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-pseudo.Set-up.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-15-pseudo.Set-up.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-pseudo.Set-up.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-15-pseudo.Unknown.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-pseudo.Unknown.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-15-pseudo.Unknown.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-pseudo.Unknown.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Both-setup.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Both-setup.png new file mode 100644 index 0000000000..c4154f28fd --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Both-setup.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3afffdf37c3f24cc5c8c331faac191d39e4838ec21c6695702f38b625888b937 +size 105856 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Key-backup-disabled.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Key-backup-disabled.png new file mode 100644 index 0000000000..6e6b1e1926 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Key-backup-disabled.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f262cd4362c5ea4d12f341badee0e253bb40c572fe5c9a8f0c8e24e8ae97b1e +size 98930 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Only-key-backup-setup.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Only-key-backup-setup.png new file mode 100644 index 0000000000..78bc3ab5cc --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Only-key-backup-setup.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b2f5bbe38921c7ea09aa97c0a50fb73342dd7594fdabfd758b23cbc02d3f4403 +size 117500 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Recovery-incomplete.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Recovery-incomplete.png new file mode 100644 index 0000000000..53cb7f4678 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Recovery-incomplete.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:00b7edaaa02c2ffcb38f79f31e9f265a4c3a837df76858bd6027742b250ed8fb +size 92190 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Both-setup.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Both-setup.png new file mode 100644 index 0000000000..7776834214 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Both-setup.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:573167b53caef5932d4f65bde0f5b2464bcfe8fe1321215af93ab5df82ad460f +size 115876 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Key-backup-disabled.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Key-backup-disabled.png new file mode 100644 index 0000000000..3e990fdee7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Key-backup-disabled.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a6cf656cead4fb620fd4fb9acd0d4038f0e75de1a9c3963d5394907ccb33664 +size 107128 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Only-key-backup-setup.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Only-key-backup-setup.png new file mode 100644 index 0000000000..24e5cbf577 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Only-key-backup-setup.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b04cdd32066178398a510f3300457171f6b020a8e37aaf30facd743618cf3e2e +size 137128 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Recovery-incomplete.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Recovery-incomplete.png new file mode 100644 index 0000000000..849dd80a4e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Recovery-incomplete.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4471d33581e3ebb69e7c83f87288f9c67267e84845606066db3e3fc88813fa2a +size 95297 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-en-GB.Both-setup.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-en-GB.Both-setup.png new file mode 100644 index 0000000000..3a84981783 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-en-GB.Both-setup.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a4e365693e03873237cd2ce745731b4e41470dc2601e6ffa807da65ff7e2d206 +size 57067 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-en-GB.Key-backup-disabled.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-en-GB.Key-backup-disabled.png new file mode 100644 index 0000000000..38bfa7c7b5 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-en-GB.Key-backup-disabled.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f51290abdc155242eafc3918e2bb3c52c7d7b1c93a0f9aea86688eba14e4f79 +size 50331 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-en-GB.Only-key-backup-setup.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-en-GB.Only-key-backup-setup.png new file mode 100644 index 0000000000..1cc3a66e26 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-en-GB.Only-key-backup-setup.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:57e926d66d843ae875930a5625cd7fbf3ec73d2fced400cc476ba2d5e30e456e +size 70109 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-en-GB.Recovery-incomplete.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-en-GB.Recovery-incomplete.png new file mode 100644 index 0000000000..e016c1794f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-en-GB.Recovery-incomplete.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:efa3569bb4408168dc0416e65de3c57406505199f92e7b81ffb697242b439a14 +size 45404 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-pseudo.Both-setup.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-pseudo.Both-setup.png new file mode 100644 index 0000000000..822706eef1 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-pseudo.Both-setup.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c2397e68ef6f1666a4b8da11d2a84306a3bd162e0464cc1d3c344eee39cb58db +size 73528 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-pseudo.Key-backup-disabled.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-pseudo.Key-backup-disabled.png new file mode 100644 index 0000000000..8b86fada2a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-pseudo.Key-backup-disabled.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:49badfad4daefe3f88eb85716cde43a3a7e81587b61d7f27551cee2d8c7c3134 +size 62528 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-pseudo.Only-key-backup-setup.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-pseudo.Only-key-backup-setup.png new file mode 100644 index 0000000000..4185dc2208 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-pseudo.Only-key-backup-setup.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa050f41d2c83f5d441011ac88a47680913f1489dcc47500d816ce797531a0e3 +size 98235 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-pseudo.Recovery-incomplete.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-pseudo.Recovery-incomplete.png new file mode 100644 index 0000000000..d47054de82 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-16-pseudo.Recovery-incomplete.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:db5c48557a3e20b0767a93b92f0f3a72351f7dd1f2ca6d89afb108aac8ff73d2 +size 53699 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-en-GB.Login.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-en-GB.Login.png new file mode 100644 index 0000000000..63b63b38e9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-en-GB.Login.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:69b7c02c864575e3e69cbf8bbc727f6124d06841c3540e33dc523b84d3bd3b73 +size 103197 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-en-GB.Register.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-en-GB.Register.png new file mode 100644 index 0000000000..163e0a3edc --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-en-GB.Register.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:663437838152f1bed1aa7f29cee3233149db54365997558fd585a5ae118187dd +size 108895 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-pseudo.Login.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-pseudo.Login.png new file mode 100644 index 0000000000..e4a873d6f1 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-pseudo.Login.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:957cdcbfcd9b91532e3a739039ea026dc4d7bb1e4dc79087baae5da22abb07cc +size 120581 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-pseudo.Register.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-pseudo.Register.png new file mode 100644 index 0000000000..fb2350f2c5 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-pseudo.Register.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:65620857fe08f2bb1afca7d221e892c1ace29a3f5d783554b45e8d6b804ae097 +size 133759 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-16-en-GB.Login.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-16-en-GB.Login.png new file mode 100644 index 0000000000..14ee51d788 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-16-en-GB.Login.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e4a361eb442339296e27e0999269fa8e248035e58a40483b3884f9ca4d145f4 +size 63625 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-16-en-GB.Register.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-16-en-GB.Register.png new file mode 100644 index 0000000000..bf678fe702 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-16-en-GB.Register.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:464018bac08f003b3ce9aa32bac694de3b0ad88ed879aa983b38c3fa4609e2d4 +size 68720 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-16-pseudo.Login.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-16-pseudo.Login.png new file mode 100644 index 0000000000..fbac181cdb --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-16-pseudo.Login.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18bb05ed7f9e9d2d6b0261cef8d6f16f86c0930b0b699e8b5ba3f4ef9d50a84f +size 87593 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-16-pseudo.Register.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-16-pseudo.Register.png new file mode 100644 index 0000000000..c60f8acd60 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-16-pseudo.Register.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:65e733035181c72339220c3ead9e272102bf0b6f1e5667d90fa766e82a5655d5 +size 98319 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.1.png new file mode 100644 index 0000000000..f080e1d32a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:439d4c6e81324776c8608a96981a2d6056cf8ea148fcb7d11d4102be3cb84226 +size 119879 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 new file mode 100644 index 0000000000..a30d966e22 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1334150c61f1c2668c7c1e11f3837ffc7c8589bcade6a3069d7370972079b0de +size 116778 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.3.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.3.png new file mode 100644 index 0000000000..8a65288344 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:667d6afdec1cad4db4439278981efc6cafb8c4bb52a28ed951120da64156481c +size 106217 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.4.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.4.png new file mode 100644 index 0000000000..bd451c4715 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.4.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d5ded2fed9334df463a22744183966ac301d7a313f79f4778aa0da4608a75246 +size 116706 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.1.png new file mode 100644 index 0000000000..daf436d890 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:33d9e3a0e09db01227458fca2f193694209a3efb430300a3445c98b9365cda7a +size 140243 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.2.png new file mode 100644 index 0000000000..b62b7e9bf5 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:30b119fc0f21681cd6cbe746044f8cf8681437f1187053b625c75ceac146b3e2 +size 137967 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.3.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.3.png new file mode 100644 index 0000000000..ac2cd11120 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:028f43f14f8ad6f5a7eef82c6bcb01779ddec20b6cda44c405ecd874bc3ed35d +size 115393 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.4.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.4.png new file mode 100644 index 0000000000..a2161add39 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.4.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0584b2d8cbec2a452768cabaeeae605e2d88b4139d3f1bb3236aaf4cd90d6d89 +size 136993 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPhone-15-en-GB.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-en-GB.2.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPhone-15-en-GB.2.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-en-GB.2.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPhone-15-en-GB.3.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-en-GB.3.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPhone-15-en-GB.3.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-en-GB.3.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPhone-15-en-GB.4.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-en-GB.4.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPhone-15-en-GB.4.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-en-GB.4.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPhone-15-pseudo.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-pseudo.2.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPhone-15-pseudo.2.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-pseudo.2.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPhone-15-pseudo.3.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-pseudo.3.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPhone-15-pseudo.3.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-pseudo.3.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPhone-15-pseudo.4.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-pseudo.4.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPhone-15-pseudo.4.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-pseudo.4.png 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 new file mode 100644 index 0000000000..7c73b1805e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Cancelled.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac1201a329e103496c67f7009b251901396831336061ae67cbf086ce1b808836 +size 94156 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Initial.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Initial.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Initial.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Initial.png 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 new file mode 100644 index 0000000000..17a218ae94 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Request-Accepted.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:39c7baba15007785521fc44cee49530a6d11ce9f528f34d09c3976e4ef6a8e7e +size 93367 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 new file mode 100644 index 0000000000..6d4290ff1e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Requesting-Verification.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c436e4722a30ab053682f23e0f9c1f3c01d0a12ae14abcfd3f79c61d66135ef4 +size 95485 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 new file mode 100644 index 0000000000..78d44f4bb1 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Showing-Challenge.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ddf03ee7b6c5909e9b69726a715a5ee957ec2bc880d6973c45c02bf9b36e829 +size 166279 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 new file mode 100644 index 0000000000..fc83a0f239 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Verified.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:39c8ee9534c65c7e4bd7eb52e70f9ceb0acef78cbcb49681806c1e9561c949b8 +size 95052 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Cancelled.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Cancelled.png new file mode 100644 index 0000000000..2625cdfda7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Cancelled.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2a0b0b7e7c459b9dac34c6f691339dbfac5ed79a25a7b7747c3f12545b7a9cee +size 106186 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Initial.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Initial.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Initial.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Initial.png 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 new file mode 100644 index 0000000000..3993cdefad --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Request-Accepted.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e49593329ca0212376e5f2122e1a27f8285771ee0276cb7eae93c77944d7964b +size 103153 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 new file mode 100644 index 0000000000..4bb8853a17 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Requesting-Verification.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7def3357b602031d5d231ad8d4924bbd69f7216a5a02a9bbcef37de5b62416e4 +size 106801 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 new file mode 100644 index 0000000000..9f19e226c5 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Showing-Challenge.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:62e03b414dc70f9319472f47d3ca14d336e858494a9f582632508ddbd335840d +size 185548 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Verified.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Verified.png new file mode 100644 index 0000000000..280d01e161 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Verified.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89a7978637d296f963f82cfc48314f5b6092e8c7296a0b7925f8e0bcf73bc6ea +size 111453 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 new file mode 100644 index 0000000000..f806c1312e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Cancelled.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:49032353a8a50c869d3da4020a77ae92b4d765d6860b530278a253f9ca2eccaa +size 52925 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-en-GB.Initial.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Initial.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-en-GB.Initial.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Initial.png 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 new file mode 100644 index 0000000000..0873c99b14 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Request-Accepted.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:261b849a3566352f91a468573264ddabdb66468e9871e41ff99e9b9f70a6c30d +size 50999 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 new file mode 100644 index 0000000000..2884cc4d66 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Requesting-Verification.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f3c8494d96db0197bdd4f01cbc4c68b3e5204620e458f54aff02a36d51557320 +size 52301 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 new file mode 100644 index 0000000000..ff52cfa4b2 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Showing-Challenge.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:871011b7284f48f2812dd183eb700dc995380240c5241d3f5aa43e0380e47423 +size 116067 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 new file mode 100644 index 0000000000..2178a70749 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Verified.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b9ea2ac42097c75194b08a1f795c5f60b152e5670d6c7610733f7fa49fe28e05 +size 52229 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 new file mode 100644 index 0000000000..73c478afe2 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Cancelled.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b14189fe0da611b4645490765a6b57b4d7baf890aaa40e18f46e730696b1ce71 +size 71794 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-pseudo.Initial.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Initial.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-pseudo.Initial.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Initial.png 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 new file mode 100644 index 0000000000..527759301d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Request-Accepted.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f7129fa293bd0f5eee4a09ea79b4a17b77f9ac470c53ce76f7fef94a74bb3c7 +size 61706 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 new file mode 100644 index 0000000000..46e31c462e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Requesting-Verification.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7a327aad0beaaa8488651dd03b411ad386820c6c42e7614a19f74736ca23c0a5 +size 69364 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 new file mode 100644 index 0000000000..1781a539fe --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Showing-Challenge.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:13db2a4db9a73e75b3af09451efed5dd29062a893a10e03627eef4251e08b5e5 +size 136557 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 new file mode 100644 index 0000000000..91d13a14c4 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Verified.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:239c4a79f7e61376d48e733752a84ef3e2ad91c66155a835094d9148ea75bb27 +size 72167 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_settingsScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_settingsScreen-iPad-en-GB.1.png new file mode 100644 index 0000000000..522f6a5846 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_settingsScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:66bf3b99fa39402357a04ebc6d403e77d5aea8cb89022f15506eb0ef64fe65ec +size 166144 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_settingsScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_settingsScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..87d3d450a3 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_settingsScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3e2262a9b8752607b64d5e96a999eb5667c5dd4506f3be1374c59054a4fece5 +size 174257 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_settingsScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_settingsScreen-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..8d385346ec --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_settingsScreen-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ce5e1bd5e6f7325fdea0332cce899a8f0c1439d971d159324d48f89ed3a58ac6 +size 106225 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_settingsScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_settingsScreen-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..8f1bfb9567 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_settingsScreen-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3755ae2d427b03ba0f591ac1358c8e74c14cb378a20a53560e342b6077562837 +size 123000 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_shimmerOverlay-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_shimmerOverlay-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_shimmerOverlay-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_shimmerOverlay-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_shimmerOverlay-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_shimmerOverlay-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_shimmerOverlay-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_shimmerOverlay-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_shimmerOverlay-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_shimmerOverlay-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_shimmerOverlay-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_shimmerOverlay-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_shimmerOverlay-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_shimmerOverlay-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_shimmerOverlay-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_shimmerOverlay-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.2.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.2.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.2.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.3.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.3.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.3.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.3.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.4.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.4.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.4.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.4.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.5.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.5.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.5.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.5.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.2.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.2.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.2.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.3.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.3.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.3.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.3.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.4.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.4.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.4.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.4.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.5.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.5.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.5.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.5.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-15-en-GB.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-en-GB.2.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-15-en-GB.2.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-en-GB.2.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-15-en-GB.3.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-en-GB.3.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-15-en-GB.3.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-en-GB.3.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-15-en-GB.4.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-en-GB.4.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-15-en-GB.4.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-en-GB.4.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-15-en-GB.5.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-en-GB.5.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-15-en-GB.5.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-en-GB.5.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-15-pseudo.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-pseudo.2.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-15-pseudo.2.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-pseudo.2.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-15-pseudo.3.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-pseudo.3.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-15-pseudo.3.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-pseudo.3.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-15-pseudo.4.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-pseudo.4.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-15-pseudo.4.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-pseudo.4.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-15-pseudo.5.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-pseudo.5.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-15-pseudo.5.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-pseudo.5.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_splashScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_splashScreen-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_splashScreen-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_splashScreen-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_splashScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_splashScreen-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_splashScreen-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_splashScreen-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_splashScreen-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_splashScreen-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_splashScreen-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_splashScreen-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_splashScreen-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_splashScreen-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_splashScreen-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_splashScreen-iPhone-16-pseudo.1.png 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 new file mode 100644 index 0000000000..5d2115edf4 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ddb7f965ab42a13e6bbbc554ac626d73591c7b8d08a99774d62aa8bc975d8630 +size 98582 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..5756279513 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0d6e81dbe187564ba5f35c650f8f45bf69f52f47579fb451d57da903cd15ee26 +size 104424 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 new file mode 100644 index 0000000000..1eeb875046 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0473f29b5a1b07b7e6599105cfe8fb9caef968c1895fbd3c342af43c4402e4da +size 51015 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 new file mode 100644 index 0000000000..2f5a3a0dea --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e499296604700dc37650b329b8ff03a82d3588f59990023bf205826f083ffd0f +size 58664 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_stateRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stateRoomTimelineView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_stateRoomTimelineView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_stateRoomTimelineView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_stateRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stateRoomTimelineView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_stateRoomTimelineView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_stateRoomTimelineView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_stateRoomTimelineView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stateRoomTimelineView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_stateRoomTimelineView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_stateRoomTimelineView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_stateRoomTimelineView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stateRoomTimelineView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_stateRoomTimelineView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_stateRoomTimelineView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-en-GB.Picker.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-en-GB.Picker.png new file mode 100644 index 0000000000..7c5c938d9b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-en-GB.Picker.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7598a01b72ef9c25f674f0a44b95c6e5fa33095516191d653e83e9be228fb275 +size 96421 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-en-GB.View-Only-with-description.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-en-GB.View-Only-with-description.png new file mode 100644 index 0000000000..db0fae6aaf --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-en-GB.View-Only-with-description.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:33c5aa2ea43d544824368846299a1b74e632997a4de8544f84512d9746abd521 +size 93451 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-en-GB.View-Only.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-en-GB.View-Only.png new file mode 100644 index 0000000000..11b51a1605 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-en-GB.View-Only.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f67b1a80b4996f0a44da9827fb7329583cc69832520b94dc172c3efeabec04e +size 90321 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-pseudo.Picker.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-pseudo.Picker.png new file mode 100644 index 0000000000..888ad2ba29 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-pseudo.Picker.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:671aab3410a4b38b56381b97d03ea91168c78f7ebc771a07132a96612fc13eca +size 99007 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-pseudo.View-Only-with-description.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-pseudo.View-Only-with-description.png new file mode 100644 index 0000000000..8cf0bb570d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-pseudo.View-Only-with-description.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e3b532c1b42985ff0c496ef9e57e80960cc9ad8077b57379d6066c47e062b0b +size 94169 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-pseudo.View-Only.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-pseudo.View-Only.png new file mode 100644 index 0000000000..34d983d001 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-pseudo.View-Only.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16b7e1b8fdff4840368d22aaca2aee1ab079ad150289ee3c5dff6ef3fdc92d6d +size 91026 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-16-en-GB.Picker.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-16-en-GB.Picker.png new file mode 100644 index 0000000000..20ad9430fe --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-16-en-GB.Picker.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5fb7e090a0097ab41c1e7de3936f724b5a1ee180b33f1a151d77cb41a3c195cf +size 53431 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-16-en-GB.View-Only-with-description.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-16-en-GB.View-Only-with-description.png new file mode 100644 index 0000000000..aa9cdef9c6 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-16-en-GB.View-Only-with-description.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ffbc2f772aec25f7f9f41101a8ddce2e25193d5d1c64c214ad1b7a061c457ba8 +size 50797 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-16-en-GB.View-Only.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-16-en-GB.View-Only.png new file mode 100644 index 0000000000..0720d2a3a2 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-16-en-GB.View-Only.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8239e36bc7ea1ab5346059dc73cf1b7e2190ff1196713cf7da689b60dd73fe2c +size 47996 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-16-pseudo.Picker.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-16-pseudo.Picker.png new file mode 100644 index 0000000000..ab37281b14 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-16-pseudo.Picker.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bb9f88677a462470942fbe56f2089253630f9ae4bb1890727e812e13e62981b9 +size 56128 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-16-pseudo.View-Only-with-description.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-16-pseudo.View-Only-with-description.png new file mode 100644 index 0000000000..bd0087be1f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-16-pseudo.View-Only-with-description.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f311432888ea7327212199e9798e003ae18b31a92b31dc06918a44423eb8215c +size 51453 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-16-pseudo.View-Only.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-16-pseudo.View-Only.png new file mode 100644 index 0000000000..8f0b16aeda --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-16-pseudo.View-Only.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cd919507149cc8894ec154e4dc631ead3b45d39a43ed00213a9155df94fca798 +size 48641 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 new file mode 100644 index 0000000000..a40034429b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bd110afc7d00be27146e58474b810415af9dc7d5ed6faf1536419f01f41f9a3a +size 404161 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPad-pseudo.1.png new file mode 100644 index 0000000000..a40034429b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bd110afc7d00be27146e58474b810415af9dc7d5ed6faf1536419f01f41f9a3a +size 404161 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 new file mode 100644 index 0000000000..3ab5d2b0bd --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef76e5d6f293ae298df0e70744ffed330e1fcb4a1e1157fbd7578e59bbe52fd4 +size 336667 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 new file mode 100644 index 0000000000..3ab5d2b0bd --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef76e5d6f293ae298df0e70744ffed330e1fcb4a1e1157fbd7578e59bbe52fd4 +size 336667 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPad-en-GB.1.png new file mode 100644 index 0000000000..100a9ae350 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7f81022274eac7cc96fa6279f08cac8f336cd6d8e9ced519e10b60c076376c50 +size 82910 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPad-pseudo.1.png new file mode 100644 index 0000000000..f45ac3e749 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e2077a6e4ee0d8027e93c99fd683ca3ec97b29564bfe48734c76677fac5f729f +size 83609 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..b8e0e0e304 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f78ee127159f80ba7a11d2843d2405b2060648c411a9882e0dccf65c03981e6 +size 43884 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..259a343081 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b07c5cdf2cc83bc512f88134fb15701737655eddafe59e166ef0409787213857 +size 44603 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_swipeToReplyView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeToReplyView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_swipeToReplyView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeToReplyView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_swipeToReplyView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeToReplyView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_swipeToReplyView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeToReplyView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_swipeToReplyView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeToReplyView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_swipeToReplyView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeToReplyView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_swipeToReplyView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeToReplyView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_swipeToReplyView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeToReplyView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_templateScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_templateScreen-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_templateScreen-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_templateScreen-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_templateScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_templateScreen-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_templateScreen-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_templateScreen-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_templateScreen-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_templateScreen-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_templateScreen-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_templateScreen-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_templateScreen-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_templateScreen-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_templateScreen-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_templateScreen-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-en-GB.Bubble-RTL.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-en-GB.Bubble-RTL.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-en-GB.Bubble-RTL.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-en-GB.Bubble-RTL.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-en-GB.Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-en-GB.Bubble.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-en-GB.Bubble.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-en-GB.Bubble.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-pseudo.Bubble-RTL.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-pseudo.Bubble-RTL.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-pseudo.Bubble-RTL.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-pseudo.Bubble-RTL.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-pseudo.Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-pseudo.Bubble.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-pseudo.Bubble.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-pseudo.Bubble.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-15-en-GB.Bubble-RTL.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-en-GB.Bubble-RTL.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-15-en-GB.Bubble-RTL.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-en-GB.Bubble-RTL.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-15-en-GB.Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-en-GB.Bubble.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-15-en-GB.Bubble.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-en-GB.Bubble.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-15-pseudo.Bubble-RTL.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-pseudo.Bubble-RTL.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-15-pseudo.Bubble-RTL.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-pseudo.Bubble-RTL.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-15-pseudo.Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-pseudo.Bubble.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-15-pseudo.Bubble.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-pseudo.Bubble.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_threadDecorator-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_threadDecorator-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_threadDecorator-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_threadDecorator-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_threadDecorator-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_threadDecorator-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_threadDecorator-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_threadDecorator-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_threadDecorator-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_threadDecorator-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_threadDecorator-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_threadDecorator-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_threadDecorator-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_threadDecorator-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_threadDecorator-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_threadDecorator-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineDeliveryStatusView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineDeliveryStatusView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineDeliveryStatusView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineDeliveryStatusView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineDeliveryStatusView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineDeliveryStatusView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineDeliveryStatusView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineDeliveryStatusView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineDeliveryStatusView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineDeliveryStatusView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineDeliveryStatusView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineDeliveryStatusView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineDeliveryStatusView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineDeliveryStatusView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineDeliveryStatusView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineDeliveryStatusView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Encryption-Indicators.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Encryption-Indicators.png new file mode 100644 index 0000000000..ec2c0f5963 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Encryption-Indicators.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:517d2adbb60ff9e40d7b0f530b05f3810f302180fed9259673afe57f2598d669 +size 174777 diff --git a/PreviewTests/__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 similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Mock-Timeline-RTL.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Mock-Timeline-RTL.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Mock-Timeline.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Mock-Timeline.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Mock-Timeline.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Mock-Timeline.png 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 new file mode 100644 index 0000000000..a66bfd00bb --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Pinned-messages.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b45a09f5c5f8ef2b33a9df690d89593a033bd059b54c5c2ab8c0f93f0276d849 +size 792454 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Replies.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Replies.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Replies.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Replies.png 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 new file mode 100644 index 0000000000..22147dedb9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Thread-decorator.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94dfce790f72ce05f4dc60fb3c1d496c75ff9cd4cf0d399642c04a3cd55939c4 +size 182264 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Encryption-Indicators.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Encryption-Indicators.png new file mode 100644 index 0000000000..7d4aeba08c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Encryption-Indicators.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:685784026c5fbf1676f2e41105303c150a8520c0588081960dd6c679cb16f86f +size 176916 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Mock-Timeline-RTL.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Mock-Timeline-RTL.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Mock-Timeline-RTL.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Mock-Timeline-RTL.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Mock-Timeline.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Mock-Timeline.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Mock-Timeline.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Mock-Timeline.png 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 new file mode 100644 index 0000000000..a66bfd00bb --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Pinned-messages.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b45a09f5c5f8ef2b33a9df690d89593a033bd059b54c5c2ab8c0f93f0276d849 +size 792454 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Replies.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Replies.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Replies.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Replies.png 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 new file mode 100644 index 0000000000..4c574799a8 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Thread-decorator.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bd08759268776f28320c82083904dbdfce23f28dbc5d5d33ee421f0a749f06b6 +size 189871 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Encryption-Indicators.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Encryption-Indicators.png new file mode 100644 index 0000000000..f2a14f4bac --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Encryption-Indicators.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ad54f532f3ec4333e004b763956ea2ffec9aecfa0c3113b423f6a9f85ac87c7 +size 127545 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-en-GB.Mock-Timeline-RTL.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Mock-Timeline-RTL.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-en-GB.Mock-Timeline-RTL.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Mock-Timeline-RTL.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-en-GB.Mock-Timeline.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Mock-Timeline.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-en-GB.Mock-Timeline.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Mock-Timeline.png 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 new file mode 100644 index 0000000000..b97c73e538 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Pinned-messages.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8ba473ce453cdd3f505411fb9cfcafb8409d073d0c737ce3716f2c251acb0bf0 +size 494165 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-en-GB.Replies.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Replies.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-en-GB.Replies.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Replies.png 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 new file mode 100644 index 0000000000..2b5ea119ef --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Thread-decorator.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ee12fa3438d396b0e7ef5abe50ca4c3fdfd906578e36e1b94b19fdbdeba50775 +size 135556 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Encryption-Indicators.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Encryption-Indicators.png new file mode 100644 index 0000000000..45fc5a690a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Encryption-Indicators.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8dd04554290d3299b0ce0a95d2304bce2d90a7c130f48a64efc6fc4b3b15727c +size 128846 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-pseudo.Mock-Timeline-RTL.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Mock-Timeline-RTL.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-pseudo.Mock-Timeline-RTL.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Mock-Timeline-RTL.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-pseudo.Mock-Timeline.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Mock-Timeline.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-pseudo.Mock-Timeline.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Mock-Timeline.png 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 new file mode 100644 index 0000000000..b97c73e538 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Pinned-messages.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8ba473ce453cdd3f505411fb9cfcafb8409d073d0c737ce3716f2c251acb0bf0 +size 494165 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-pseudo.Replies.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Replies.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-pseudo.Replies.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Replies.png 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 new file mode 100644 index 0000000000..9a55ba4585 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Thread-decorator.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:de203ede489e3b3a48dc5cf171a0faa86f56b7993e4372c124b48d34632c9389 +size 138215 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPad-en-GB.1.png new file mode 100644 index 0000000000..e5b4b55710 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bedf892ad453c0e2d6a157fc3a38a7cf964e2509d3e24885c7b31683aa46a979 +size 113653 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPad-pseudo.1.png new file mode 100644 index 0000000000..2e8093ba10 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:752f6b8424b70f58443df241049e7e2706836d94d81ff73b14b460c048c3d6c6 +size 115193 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..bed3e4ee1e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e8a1c81979803d04546d37f153017199c560cffe91f12d132449784849f00903 +size 69227 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..316be7a3bf --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:69d3cf0672978bc46113354cb6b7ead0b815f1db78a51d1e355a2d7c06fcc7cc +size 70107 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 new file mode 100644 index 0000000000..748dad4fa7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Authenticity.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:03139a4b36b40b979854ab2659f8bef19a4415a07a7922e13f22bfafbce96362 +size 139155 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 new file mode 100644 index 0000000000..d284619294 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Button-shapes.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d4bcf22687551f169a13c2b242ba0bc2fd20d93f1438a2a99263c4fde6677ff9 +size 146820 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 new file mode 100644 index 0000000000..2e6a92bbe8 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Identity-Changed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1e4244ced22d9ba2c2938a9939512fb8202d1e5f471fc0d00f58b58845abad2c +size 137736 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 new file mode 100644 index 0000000000..ee70aed177 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Normal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26ea8ac5f8d377083815e42276831a7def7ec4d2c0ed5b118d431a362b4a123e +size 128100 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 new file mode 100644 index 0000000000..c652521a45 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Own-Unsigned-Devices.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:afa8b6189392fe1053312c29995783017ff9697b85f8960a75ecb76a83e05446 +size 138537 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 new file mode 100644 index 0000000000..7305c77aac --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unencrypted.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:36fa2f45e35a597c0c0dfe672616bc584f12e93c8d742c2fcdc0a40195dd7159 +size 132986 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 new file mode 100644 index 0000000000..ee70aed177 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unknown-failure.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26ea8ac5f8d377083815e42276831a7def7ec4d2c0ed5b118d431a362b4a123e +size 128100 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 new file mode 100644 index 0000000000..59cc5be713 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unsigned-Devices.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1583ad4ade4b6eac9eface5466a742999213b9f4e2e80ac62d174338722d6799 +size 137445 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 new file mode 100644 index 0000000000..f3f4460871 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unsigned.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c80e3745e88d27713eebb5f28fe4ee1bcc65e8690e30cba71c83b6a240a818ac +size 136759 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Authenticity.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Authenticity.png new file mode 100644 index 0000000000..54692b74c7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Authenticity.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:faa541dc8e53791b4f0fbe78a3ef2f99afcff7b91fe9f6e6293ea831baf15b07 +size 146264 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 new file mode 100644 index 0000000000..eff2c1eda6 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Button-shapes.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:403ddbf0882f5ded4fbd1ac0e34d635909f260dd2f2988a979503ca29c59db5b +size 148734 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 new file mode 100644 index 0000000000..9c0a9cd5f6 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Identity-Changed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4dd28156f64422ca6df2dc5178afdf6e3d840ab220e2e17bb55d55f3f306f359 +size 145601 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Normal.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Normal.png new file mode 100644 index 0000000000..09237aa4aa --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Normal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:25d707eeb27e5fbb22a6ec3efe70142b8781a3ea5423d44d284deebd78bfda22 +size 129934 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 new file mode 100644 index 0000000000..bf4efa013a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Own-Unsigned-Devices.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4b3d27ebbcc1acf240e82893f4ea815bb117e8e7f033aa368983ef59e48e60bf +size 144624 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unencrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unencrypted.png new file mode 100644 index 0000000000..4e5a87fe62 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unencrypted.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ffbe89eadebb2a4590f2c8d5cfb2d053eafd190f7512c7b560d73fe057bc2419 +size 137105 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 new file mode 100644 index 0000000000..09237aa4aa --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unknown-failure.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:25d707eeb27e5fbb22a6ec3efe70142b8781a3ea5423d44d284deebd78bfda22 +size 129934 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 new file mode 100644 index 0000000000..a64e8653ce --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unsigned-Devices.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd14d07d1258d5740e90cb017b42cb7715c61a7eb9ac0211ee1af57a0eac71fa +size 143967 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unsigned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unsigned.png new file mode 100644 index 0000000000..ec0208b752 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unsigned.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:039542c53b6877e128483381d0aa599d454401b60017eee2d73817d4475cfcfa +size 142473 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 new file mode 100644 index 0000000000..3d5951fd17 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Authenticity.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe429e48ab5e9733b17383b056d882cd73fec21dd79fd8fed6ef295a77c02b9c +size 91910 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 new file mode 100644 index 0000000000..74bd759561 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Button-shapes.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f7d5688fb1e653dd4d7c025496bf21c4794566772028a4fcb164255be5829ef7 +size 91186 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 new file mode 100644 index 0000000000..793e5ea724 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Identity-Changed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:09d0ef69aac97f605af70dee72274600e243d95b896e06ff4a5b88edfcbe492f +size 90909 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 new file mode 100644 index 0000000000..7a688e37bd --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Normal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca46714baac623515ee64da0f80cb8588938dc322446e8100c2fa19c80c4103e +size 81690 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 new file mode 100644 index 0000000000..173e3df801 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Own-Unsigned-Devices.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b668de157b45f5f1f75e9485d3c35e8a103428ac03563ff851b24111f3699553 +size 91806 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 new file mode 100644 index 0000000000..0982b3fddc --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Unencrypted.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6533795aeb46d968aa65e814a8a6f16d8da8806ef367400d2ef7fddb19ffc0a6 +size 84498 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 new file mode 100644 index 0000000000..7a688e37bd --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Unknown-failure.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca46714baac623515ee64da0f80cb8588938dc322446e8100c2fa19c80c4103e +size 81690 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 new file mode 100644 index 0000000000..79ea6f9974 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Unsigned-Devices.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1ebc67234b0185ddea83263dd44cd4f90dc578698d2cc40baa64167f87c28f88 +size 90370 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 new file mode 100644 index 0000000000..16b2f95c14 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Unsigned.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea7194599f6f232bcd6e2b4bf6a23095d8bdeba217ccfc5c1e53326e02118c5f +size 87424 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 new file mode 100644 index 0000000000..4c71bda155 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Authenticity.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14f96e9cc4c72a8be248885673df3b678d99b7a5227ea4751c37d027de86b543 +size 107635 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 new file mode 100644 index 0000000000..9caa67cb73 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Button-shapes.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:917f4a8cdf90f2dec6ec9812bd19d6a87611376c007d5ab528aac8ca81fdafb0 +size 96764 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 new file mode 100644 index 0000000000..d64e40d969 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Identity-Changed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:439d46bc024a1c7a387e674f454f9b67fb78276d5761b88a86dc2b399daa3629 +size 105944 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 new file mode 100644 index 0000000000..439c073c12 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Normal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8bf1639b2cf203490b7c0e0e801274fc7fd05b3942ebb9684e224192e1f1ca12 +size 87380 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 new file mode 100644 index 0000000000..e37222e437 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Own-Unsigned-Devices.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a9283c5c852d4843ee9d58b2af0df2c4effc4693f47100b232bdb5cf7c7157c1 +size 108300 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 new file mode 100644 index 0000000000..c3e375e9a6 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Unencrypted.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:55119111fd3419c9a280b49eaac288c4ff1da935280eb785815891e59dec6a4c +size 91962 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 new file mode 100644 index 0000000000..439c073c12 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Unknown-failure.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8bf1639b2cf203490b7c0e0e801274fc7fd05b3942ebb9684e224192e1f1ca12 +size 87380 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 new file mode 100644 index 0000000000..acb4756545 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Unsigned-Devices.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa27e929fdcb97f2900eb540c9e0fdbce42dabacd99c1b8a84aa761406cb7e25 +size 104293 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 new file mode 100644 index 0000000000..1065904980 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Unsigned.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67a6b2f31d5cd87a54558c93ee7f56a6af75b9887f2cbad4b28aca781696b923 +size 99497 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemSendInfoLabel-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemSendInfoLabel-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemSendInfoLabel-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemSendInfoLabel-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemSendInfoLabel-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemSendInfoLabel-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemSendInfoLabel-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemSendInfoLabel-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemSendInfoLabel-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemSendInfoLabel-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemSendInfoLabel-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemSendInfoLabel-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemSendInfoLabel-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemSendInfoLabel-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemSendInfoLabel-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemSendInfoLabel-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles-LTR-with-different-layout-languages.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles-LTR-with-different-layout-languages.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles-LTR-with-different-layout-languages.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles-LTR-with-different-layout-languages.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles-RTL-with-different-layout-languages.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles-RTL-with-different-layout-languages.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles-RTL-with-different-layout-languages.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles-RTL-with-different-layout-languages.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles-LTR-with-different-layout-languages.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles-LTR-with-different-layout-languages.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles-LTR-with-different-layout-languages.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles-LTR-with-different-layout-languages.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles-RTL-with-different-layout-languages.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles-RTL-with-different-layout-languages.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles-RTL-with-different-layout-languages.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles-RTL-with-different-layout-languages.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-15-en-GB.Bubbles-LTR-with-different-layout-languages.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-en-GB.Bubbles-LTR-with-different-layout-languages.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-15-en-GB.Bubbles-LTR-with-different-layout-languages.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-en-GB.Bubbles-LTR-with-different-layout-languages.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-15-en-GB.Bubbles-RTL-with-different-layout-languages.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-en-GB.Bubbles-RTL-with-different-layout-languages.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-15-en-GB.Bubbles-RTL-with-different-layout-languages.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-en-GB.Bubbles-RTL-with-different-layout-languages.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-15-en-GB.Bubbles.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-en-GB.Bubbles.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-15-en-GB.Bubbles.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-en-GB.Bubbles.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-15-pseudo.Bubbles-LTR-with-different-layout-languages.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-pseudo.Bubbles-LTR-with-different-layout-languages.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-15-pseudo.Bubbles-LTR-with-different-layout-languages.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-pseudo.Bubbles-LTR-with-different-layout-languages.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-15-pseudo.Bubbles-RTL-with-different-layout-languages.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-pseudo.Bubbles-RTL-with-different-layout-languages.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-15-pseudo.Bubbles-RTL-with-different-layout-languages.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-pseudo.Bubbles-RTL-with-different-layout-languages.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-15-pseudo.Bubbles.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-pseudo.Bubbles.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-15-pseudo.Bubbles.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-pseudo.Bubbles.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReactionView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReactionView-iPad-en-GB.1.png new file mode 100644 index 0000000000..2bad8f6bf9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReactionView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f7a2e751eb9487af0d565791fa81a000555f8046977f58bfd086e3689198ffe0 +size 159159 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReactionView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReactionView-iPad-pseudo.1.png new file mode 100644 index 0000000000..4976b6c81b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReactionView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dbade91dea72b1c36a84872cddeb18328112f4870ab5905c2011422dd5dc9de0 +size 150351 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReactionView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReactionView-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..fe58444118 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReactionView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d467db4873c5b79daa94cc0f7d921c22c56aefaea35253c11beaf6f348dec088 +size 106679 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReactionView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReactionView-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..0202190356 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReactionView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2be8f18b33344c9339358d3271f918ebffd02faa4dd2bc05f16dec922bea54c7 +size 98836 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineReplyView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReplyView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineReplyView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReplyView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineReplyView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReplyView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineReplyView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReplyView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineReplyView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReplyView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineReplyView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReplyView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineReplyView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReplyView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineReplyView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReplyView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineStartRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineStartRoomTimelineView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineStartRoomTimelineView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineStartRoomTimelineView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineStartRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineStartRoomTimelineView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineStartRoomTimelineView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineStartRoomTimelineView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineStartRoomTimelineView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineStartRoomTimelineView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineStartRoomTimelineView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineStartRoomTimelineView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineStartRoomTimelineView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineStartRoomTimelineView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_timelineStartRoomTimelineView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineStartRoomTimelineView-iPhone-16-pseudo.1.png 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 new file mode 100644 index 0000000000..16e7cc7bbc --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dbba95d7bded549e3b54dd8468f44f338f75df9dc2d384c800ca69d240c526bb +size 295572 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPad-pseudo.1.png new file mode 100644 index 0000000000..74310722a3 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0d28a596ca48a0cd680be7014adef2f2aac11aaf1592676da57b942bd3329708 +size 297527 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 new file mode 100644 index 0000000000..e044e0e64d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fbfaf40b0602964736bbe6dc41beea21d1733c8ec0b84c82e0c547596c4032f0 +size 180515 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 new file mode 100644 index 0000000000..f8a53763cf --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c928084fecfee3ff804ebc41d17b3433fe7dea94f7c0c82ef7c40175203061f +size 178534 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_typingIndicatorView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_typingIndicatorView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_typingIndicatorView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_typingIndicatorView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_typingIndicatorView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_typingIndicatorView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_typingIndicatorView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_typingIndicatorView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPhone-16-pseudo.1.png 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 new file mode 100644 index 0000000000..0860a9b4c0 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:361976f6d1d6b589568f339c30fa9e3842a15e85710384b5e57a1d088ac4798c +size 103492 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..a2ac943d11 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c4fd2ddd632040754d987a2554b87bd965c168201e35f08cb218b14db5d0f9b0 +size 105623 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 new file mode 100644 index 0000000000..0ba2b1bbe9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:37939e37fb95a886500d75fd3a59074a06e47547402c7339a23de76a1d23d03e +size 54682 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 new file mode 100644 index 0000000000..867dc9ad2e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd4d09599c5a8ea2b74d7d61ea493f927c763dc53e7a71ef784852e93f2cd07a +size 57980 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-en-GB.No-progress.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-en-GB.No-progress.png new file mode 100644 index 0000000000..1b627d7f87 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-en-GB.No-progress.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d681ba65fbd9d56483b2fd90f87de7a5234cbb5510c22be154093354aabbb8c7 +size 90434 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-en-GB.Progress-Bar.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-en-GB.Progress-Bar.png new file mode 100644 index 0000000000..9d48066c8c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-en-GB.Progress-Bar.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:46ae1f8079fb0d6fecf0f06c47f61c2f37d014f0d615aab79fd7c75639c5415f +size 91303 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-en-GB.Spinner.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-en-GB.Spinner.png new file mode 100644 index 0000000000..963819cbdd --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-en-GB.Spinner.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f6a2f85477fa536362b84331e745b5c84853f45cd3d21b74d4cba470aebc75b3 +size 92654 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-pseudo.No-progress.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-pseudo.No-progress.png new file mode 100644 index 0000000000..1b627d7f87 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-pseudo.No-progress.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d681ba65fbd9d56483b2fd90f87de7a5234cbb5510c22be154093354aabbb8c7 +size 90434 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-pseudo.Progress-Bar.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-pseudo.Progress-Bar.png new file mode 100644 index 0000000000..9d48066c8c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-pseudo.Progress-Bar.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:46ae1f8079fb0d6fecf0f06c47f61c2f37d014f0d615aab79fd7c75639c5415f +size 91303 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-pseudo.Spinner.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-pseudo.Spinner.png new file mode 100644 index 0000000000..963819cbdd --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-pseudo.Spinner.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f6a2f85477fa536362b84331e745b5c84853f45cd3d21b74d4cba470aebc75b3 +size 92654 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-16-en-GB.No-progress.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-16-en-GB.No-progress.png new file mode 100644 index 0000000000..c7ee6abcae --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-16-en-GB.No-progress.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:71c1e2e09b6212572ca3f443f9bb4ebeb2e4cf2182d818702fd11cb1587db9a0 +size 42593 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-16-en-GB.Progress-Bar.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-16-en-GB.Progress-Bar.png new file mode 100644 index 0000000000..e4e3f83350 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-16-en-GB.Progress-Bar.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:57244d7c4e1affdbd4c25aeca1df48d547cb640a95a0262d45fa1384d6cdc260 +size 42509 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-16-en-GB.Spinner.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-16-en-GB.Spinner.png new file mode 100644 index 0000000000..9f6a53683d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-16-en-GB.Spinner.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d526453ba493b0723873363408a530c42ae1511dcb9af505f3aaf5a9c1d9953 +size 43297 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-16-pseudo.No-progress.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-16-pseudo.No-progress.png new file mode 100644 index 0000000000..c7ee6abcae --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-16-pseudo.No-progress.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:71c1e2e09b6212572ca3f443f9bb4ebeb2e4cf2182d818702fd11cb1587db9a0 +size 42593 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-16-pseudo.Progress-Bar.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-16-pseudo.Progress-Bar.png new file mode 100644 index 0000000000..e4e3f83350 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-16-pseudo.Progress-Bar.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:57244d7c4e1affdbd4c25aeca1df48d547cb640a95a0262d45fa1384d6cdc260 +size 42509 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-16-pseudo.Spinner.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-16-pseudo.Spinner.png new file mode 100644 index 0000000000..9f6a53683d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-16-pseudo.Spinner.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d526453ba493b0723873363408a530c42ae1511dcb9af505f3aaf5a9c1d9953 +size 43297 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPad-en-GB.1.png new file mode 100644 index 0000000000..58d6b5632b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1a1ddb695450412ad2cea3b0109bb944319a3cde7f6b5fa10b5b66e39b484883 +size 98613 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPad-pseudo.1.png new file mode 100644 index 0000000000..58d6b5632b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1a1ddb695450412ad2cea3b0109bb944319a3cde7f6b5fa10b5b66e39b484883 +size 98613 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..4fa8ed3f47 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7383c3645e8e3fce81afdd844bcfc2a0b87553e3d980ce0cd559cf37647e996a +size 54716 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..4fa8ed3f47 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7383c3645e8e3fce81afdd844bcfc2a0b87553e3d980ce0cd559cf37647e996a +size 54716 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userProfileCell-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileCell-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_userProfileCell-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileCell-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userProfileCell-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileCell-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_userProfileCell-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileCell-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userProfileCell-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileCell-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_userProfileCell-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileCell-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userProfileCell-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileCell-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_userProfileCell-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileCell-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userProfileScreen-iPad-en-GB.Account-Owner.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileScreen-iPad-en-GB.Account-Owner.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_userProfileScreen-iPad-en-GB.Account-Owner.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileScreen-iPad-en-GB.Account-Owner.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userProfileScreen-iPad-en-GB.Other-User.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileScreen-iPad-en-GB.Other-User.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_userProfileScreen-iPad-en-GB.Other-User.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileScreen-iPad-en-GB.Other-User.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userProfileScreen-iPad-pseudo.Account-Owner.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileScreen-iPad-pseudo.Account-Owner.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_userProfileScreen-iPad-pseudo.Account-Owner.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileScreen-iPad-pseudo.Account-Owner.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userProfileScreen-iPad-pseudo.Other-User.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileScreen-iPad-pseudo.Other-User.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_userProfileScreen-iPad-pseudo.Other-User.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileScreen-iPad-pseudo.Other-User.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userProfileScreen-iPhone-15-en-GB.Account-Owner.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileScreen-iPhone-16-en-GB.Account-Owner.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_userProfileScreen-iPhone-15-en-GB.Account-Owner.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileScreen-iPhone-16-en-GB.Account-Owner.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userProfileScreen-iPhone-15-en-GB.Other-User.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileScreen-iPhone-16-en-GB.Other-User.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_userProfileScreen-iPhone-15-en-GB.Other-User.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileScreen-iPhone-16-en-GB.Other-User.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userProfileScreen-iPhone-15-pseudo.Account-Owner.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileScreen-iPhone-16-pseudo.Account-Owner.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_userProfileScreen-iPhone-15-pseudo.Account-Owner.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileScreen-iPhone-16-pseudo.Account-Owner.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userProfileScreen-iPhone-15-pseudo.Other-User.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileScreen-iPhone-16-pseudo.Other-User.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_userProfileScreen-iPhone-15-pseudo.Other-User.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_userProfileScreen-iPhone-16-pseudo.Other-User.png 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 new file mode 100644 index 0000000000..1bc9dd26dc --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:919c37cec762f3a5ead4e55e611e78bc3b6a52fdb6c2f2435d387511bdaf3bb3 +size 81177 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPad-pseudo.1.png new file mode 100644 index 0000000000..1bc9dd26dc --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:919c37cec762f3a5ead4e55e611e78bc3b6a52fdb6c2f2435d387511bdaf3bb3 +size 81177 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 new file mode 100644 index 0000000000..15d62f2135 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bbf8a9e38c8188356a7e9758b7afbcbc84c4b58b4ada32999e1591883c99704c +size 40312 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 new file mode 100644 index 0000000000..15d62f2135 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bbf8a9e38c8188356a7e9758b7afbcbc84c4b58b4ada32999e1591883c99704c +size 40312 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageButton-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageButton-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageButton-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageButton-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageButton-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageButton-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageButton-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageButton-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageButton-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageButton-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageButton-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageButton-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageButton-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageButton-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageButton-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageButton-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessagePreviewComposer-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessagePreviewComposer-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessagePreviewComposer-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessagePreviewComposer-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessagePreviewComposer-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessagePreviewComposer-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessagePreviewComposer-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessagePreviewComposer-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessagePreviewComposer-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessagePreviewComposer-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessagePreviewComposer-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessagePreviewComposer-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessagePreviewComposer-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessagePreviewComposer-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessagePreviewComposer-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessagePreviewComposer-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingButton-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingButton-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingButton-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingButton-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingButton-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingButton-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingButton-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingButton-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingButton-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingButton-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingButton-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingButton-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingButton-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingButton-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingButton-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingButton-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingComposer-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingComposer-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingComposer-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingComposer-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingComposer-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingComposer-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingComposer-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingComposer-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingComposer-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingComposer-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingComposer-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingComposer-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingComposer-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingComposer-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingComposer-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingComposer-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRecordingView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRoomPlaybackView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomPlaybackView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRoomPlaybackView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomPlaybackView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRoomPlaybackView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomPlaybackView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRoomPlaybackView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomPlaybackView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRoomPlaybackView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomPlaybackView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRoomPlaybackView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomPlaybackView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRoomPlaybackView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomPlaybackView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRoomPlaybackView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomPlaybackView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-en-GB.Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-en-GB.Bubble.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-en-GB.Bubble.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-en-GB.Bubble.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-pseudo.Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-pseudo.Bubble.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-pseudo.Bubble.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-pseudo.Bubble.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPhone-15-en-GB.Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPhone-16-en-GB.Bubble.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPhone-15-en-GB.Bubble.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPhone-16-en-GB.Bubble.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPhone-15-pseudo.Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPhone-16-pseudo.Bubble.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPhone-15-pseudo.Bubble.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPhone-16-pseudo.Bubble.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_waitingDialog-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitingDialog-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_waitingDialog-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitingDialog-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_waitingDialog-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitingDialog-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_waitingDialog-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitingDialog-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_waitingDialog-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitingDialog-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_waitingDialog-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitingDialog-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_waitingDialog-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitingDialog-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_waitingDialog-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitingDialog-iPhone-16-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_waitlistScreen-iPad-en-GB.Success.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitlistScreen-iPad-en-GB.Success.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_waitlistScreen-iPad-en-GB.Success.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitlistScreen-iPad-en-GB.Success.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_waitlistScreen-iPad-en-GB.Waiting.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitlistScreen-iPad-en-GB.Waiting.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_waitlistScreen-iPad-en-GB.Waiting.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitlistScreen-iPad-en-GB.Waiting.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_waitlistScreen-iPad-pseudo.Success.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitlistScreen-iPad-pseudo.Success.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_waitlistScreen-iPad-pseudo.Success.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitlistScreen-iPad-pseudo.Success.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_waitlistScreen-iPad-pseudo.Waiting.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitlistScreen-iPad-pseudo.Waiting.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_waitlistScreen-iPad-pseudo.Waiting.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitlistScreen-iPad-pseudo.Waiting.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_waitlistScreen-iPhone-15-en-GB.Success.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitlistScreen-iPhone-16-en-GB.Success.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_waitlistScreen-iPhone-15-en-GB.Success.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitlistScreen-iPhone-16-en-GB.Success.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_waitlistScreen-iPhone-15-en-GB.Waiting.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitlistScreen-iPhone-16-en-GB.Waiting.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_waitlistScreen-iPhone-15-en-GB.Waiting.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitlistScreen-iPhone-16-en-GB.Waiting.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_waitlistScreen-iPhone-15-pseudo.Success.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitlistScreen-iPhone-16-pseudo.Success.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_waitlistScreen-iPhone-15-pseudo.Success.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitlistScreen-iPhone-16-pseudo.Success.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_waitlistScreen-iPhone-15-pseudo.Waiting.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitlistScreen-iPhone-16-pseudo.Waiting.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_waitlistScreen-iPhone-15-pseudo.Waiting.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_waitlistScreen-iPhone-16-pseudo.Waiting.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_waveformCursorView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_waveformCursorView-iPad-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_waveformCursorView-iPad-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_waveformCursorView-iPad-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_waveformCursorView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_waveformCursorView-iPad-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_waveformCursorView-iPad-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_waveformCursorView-iPad-pseudo.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_waveformCursorView-iPhone-15-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_waveformCursorView-iPhone-16-en-GB.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_waveformCursorView-iPhone-15-en-GB.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_waveformCursorView-iPhone-16-en-GB.1.png diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_waveformCursorView-iPhone-15-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_waveformCursorView-iPhone-16-pseudo.1.png similarity index 100% rename from PreviewTests/__Snapshots__/PreviewTests/test_waveformCursorView-iPhone-15-pseudo.1.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_waveformCursorView-iPhone-16-pseudo.1.png diff --git a/PreviewTests/SupportingFiles/PreviewTests.xctestplan b/PreviewTests/SupportingFiles/PreviewTests.xctestplan index 966c06bdfd..51bb5f4e75 100644 --- a/PreviewTests/SupportingFiles/PreviewTests.xctestplan +++ b/PreviewTests/SupportingFiles/PreviewTests.xctestplan @@ -31,6 +31,11 @@ { "key" : "IS_RUNNING_UNIT_TESTS", "value" : "1" + }, + { + "enabled" : false, + "key" : "RECORD_FAILURES", + "value" : "true" } ], "testExecutionOrdering" : "random", diff --git a/PreviewTests/SupportingFiles/target.yml b/PreviewTests/SupportingFiles/target.yml index 1b4bf51d13..d0620f3343 100644 --- a/PreviewTests/SupportingFiles/target.yml +++ b/PreviewTests/SupportingFiles/target.yml @@ -29,10 +29,6 @@ targets: type: bundle.unit-test platform: iOS - buildToolPlugins: - - plugin: PrefireTestsPlugin - package: Prefire - dependencies: - target: ElementX - package: SnapshotTesting @@ -48,4 +44,7 @@ targets: release: sources: + - path: ../Sources + excludes: + - "**/__Snapshots__/**" - path: ../SupportingFiles diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPad-en-GB.1.png deleted file mode 100644 index 6fd1ffe8fb..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5098e8febb522533a164ea49f50bd049d0f7d273210476fcf43106349b18d746 -size 112936 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPad-pseudo.1.png deleted file mode 100644 index 92313d245d..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e314cb293d55bc73c9b9882aaee4a75fe7cf57a1d2c77d2010c001a597b63a95 -size 126399 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPhone-15-en-GB.1.png deleted file mode 100644 index 0c1daa2273..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:18f7db074cbe0d70b888d436287f6831b44735cb84c3809a02a977825ee45c41 -size 66590 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPhone-15-pseudo.1.png deleted file mode 100644 index 1a12a5cfa2..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_advancedSettingsScreen-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7a604cc7c506dbfdb0f465a9b00339101e7dd01a8552c0a716ce2f572b20fed2 -size 83990 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPad-en-GB.1.png deleted file mode 100644 index 546a8cb345..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3f008b0b91873db9b4102bf8508a78372db9440f577c609e1677837e19561dbb -size 111069 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPad-pseudo.1.png deleted file mode 100644 index 113986fcf9..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:668a9c0536b5155b7bf07e6b8fc7de64e94c15868d5efee11cdb771d9cf2175d -size 118743 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPhone-15-en-GB.1.png deleted file mode 100644 index bb8419e8a5..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:82b98dbc5b90e4f3432d4d311cf98b1f8762e22b7b4437364030633782145f38 -size 73447 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPhone-15-pseudo.1.png deleted file mode 100644 index 66c4a8b356..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreenCheckmarkItem-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3701ce1293f61e7b35abfe35d13f5860c1a87136ecaa3d3406e8d0dd117a6b14 -size 87369 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockScreen-iPad-en-GB.1.png deleted file mode 100644 index 38692eb038..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8b079a6750fcaae622ee5b104e6eb1d2dd9e9ce560ea21a3e59d394ea39b1578 -size 114681 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockScreen-iPad-pseudo.1.png deleted file mode 100644 index 15a0c6f111..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e074dc779b28db695da4291d48a843083ab2ed3a37d60cf5d120379c3e90c7ba -size 123067 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockScreen-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockScreen-iPhone-15-en-GB.1.png deleted file mode 100644 index fc50cecbdc..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockScreen-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7271a235ebd28e27681eaeabc74ae3d2694dfd9009c0bb7c7eef377f3061773f -size 70777 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockScreen-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockScreen-iPhone-15-pseudo.1.png deleted file mode 100644 index ef87e5660f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockScreen-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:68644465e33c39d540d08d61632705359753b84e85df700052340d9864f41cd8 -size 77623 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-en-GB.Face-ID.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-en-GB.Face-ID.png deleted file mode 100644 index 7e9fbe0de3..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-en-GB.Face-ID.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e1185f3149926908e18fc3cb965ba3931bd76f8b72aaa6c081647a2d488ce79d -size 98717 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-en-GB.Touch-ID.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-en-GB.Touch-ID.png deleted file mode 100644 index 88b707d362..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-en-GB.Touch-ID.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6b5d3819f144534d794c57aa512b154314196c3b35747ca926e586352f88631b -size 107059 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-pseudo.Face-ID.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-pseudo.Face-ID.png deleted file mode 100644 index 9a52dd493a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-pseudo.Face-ID.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:df306effa6fe58269811225d3fc0d19fa31ba652355bfff7d725b00387534508 -size 112133 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-pseudo.Touch-ID.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-pseudo.Touch-ID.png deleted file mode 100644 index 8644af43dd..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPad-pseudo.Touch-ID.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a6cb494828af912b2e722689df630df96febdda6fa6de254d08e1bc4e36331c5 -size 122066 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPhone-15-en-GB.Face-ID.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPhone-15-en-GB.Face-ID.png deleted file mode 100644 index ac8450e688..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPhone-15-en-GB.Face-ID.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:64aba3ab8685c7cb50cd0da6cc38a52b9682ad8ddcf8d743e7932b1c3c3ee630 -size 57308 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPhone-15-pseudo.Face-ID.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPhone-15-pseudo.Face-ID.png deleted file mode 100644 index 53d7ab7779..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupBiometricsScreen-iPhone-15-pseudo.Face-ID.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ca5fd5daf821b64e84e921f35c37d18671fac074d4b7697357422e66d2f4f95f -size 73303 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Confirm.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Confirm.png deleted file mode 100644 index a8ff89fa29..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Confirm.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5922b6a330c096c0686a8128566714e7626e3fd1f8682b50a9bf75aaca5f9569 -size 99568 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Create.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Create.png deleted file mode 100644 index 10a25c9433..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Create.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b5ec60ac0e1b77235dd08fbd5e14fbb37ee9f42e1199c9eaf232759652d7adce -size 99985 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Unlock-Failed.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Unlock-Failed.png deleted file mode 100644 index 8df699cc55..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Unlock-Failed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:641c3c085bc438ce97679deca21b6ece615db80c8091aad5230db249229f0df3 -size 90985 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Unlock.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Unlock.png deleted file mode 100644 index 91770273d0..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-en-GB.Unlock.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ad4521af99376c414502cdaabca8b4d6d6c91afd7d55867a45a9d3d9283a72d7 -size 89696 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Confirm.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Confirm.png deleted file mode 100644 index fb8e0068cc..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Confirm.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0b059a0e1069e9a0d4b71effcb2b92e6bd7d75719deed87dcb8db5bc685364d1 -size 118852 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Create.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Create.png deleted file mode 100644 index 31bde0d1d3..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Create.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dd1fa6ec01b866375ba36673b738f00f16bf57d6e7281343348bc7379475c494 -size 119211 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Unlock-Failed.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Unlock-Failed.png deleted file mode 100644 index c2220df019..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Unlock-Failed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:82687be353cafb7ec3e8da2333ff07d9c040732dcf9f9a3ec23681055ce0f697 -size 94116 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Unlock.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Unlock.png deleted file mode 100644 index 33020edc6e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupPINScreen-iPad-pseudo.Unlock.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:209b952077441c3053be9d2b514a24404b3043e7664a624ed2764ea85e10d40f -size 93919 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-en-GB.Face-ID.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-en-GB.Face-ID.png deleted file mode 100644 index ba78cea82b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-en-GB.Face-ID.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ec2c2f47f0135af7758fad4d59866aeb3c47c9ff3a7a6c9cc48e82af86cf5ea2 -size 96981 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-en-GB.PIN-only.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-en-GB.PIN-only.png deleted file mode 100644 index ffcee5427c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-en-GB.PIN-only.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:132cead04ae998a039b9413b193d4e52f6026c0c1160dc3e11ff69699e9c0234 -size 89534 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-en-GB.Touch-ID-Mandatory.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-en-GB.Touch-ID-Mandatory.png deleted file mode 100644 index b2b9527f7d..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-en-GB.Touch-ID-Mandatory.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4c77258aa2aeb2796a3e33b9e0a35bb056f0012cc559889bb16cce22e36fe51d -size 92515 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-pseudo.Face-ID.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-pseudo.Face-ID.png deleted file mode 100644 index f3883653fd..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-pseudo.Face-ID.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:33f49dff77e6615185dab79ae24d09615f04a32d56edde006bfbe66bf33dab14 -size 105473 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-pseudo.PIN-only.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-pseudo.PIN-only.png deleted file mode 100644 index cec7805e48..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-pseudo.PIN-only.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9c8006261f925d143a7702f5a4d7f16aa4ee7e1f68e53e08ddc39ee5b6cbd943 -size 94248 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-pseudo.Touch-ID-Mandatory.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-pseudo.Touch-ID-Mandatory.png deleted file mode 100644 index 906a91b810..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPad-pseudo.Touch-ID-Mandatory.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:773e1134128bb35979bb19e82e9c286a73598baa304cb02d18a5080b5b0fc7b5 -size 100047 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-15-en-GB.Face-ID.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-15-en-GB.Face-ID.png deleted file mode 100644 index 1666fa5de9..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-15-en-GB.Face-ID.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:41c0b7a7337aebd06d760c380f09962f8d74e3312998b6c5d038d96d602d6217 -size 48742 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-15-en-GB.PIN-only.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-15-en-GB.PIN-only.png deleted file mode 100644 index 6cdadf00a5..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-15-en-GB.PIN-only.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9529b21243d48a7e7887f447170eb6ee65c943debcdd3a68b421fdab4884cf26 -size 42332 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-15-en-GB.Touch-ID-Mandatory.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-15-en-GB.Touch-ID-Mandatory.png deleted file mode 100644 index 3f4233008e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-15-en-GB.Touch-ID-Mandatory.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5a39ba86e64d5ce7610c505ce219f3f4ff12c8b989fd5e2ed5ce639a27bf1747 -size 45410 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-15-pseudo.Face-ID.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-15-pseudo.Face-ID.png deleted file mode 100644 index 7edec512fb..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-15-pseudo.Face-ID.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d7b7ce5eabd1f1251d8be7e5f6ac19c99d61ad35cc6cbf6814be2031a36b5e09 -size 56450 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-15-pseudo.PIN-only.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-15-pseudo.PIN-only.png deleted file mode 100644 index 2804b27e15..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-15-pseudo.PIN-only.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:48410b4fb132f4cb7900f3a16f9f8cfe14cd14c4f1c6d0b86afcac1d9583e5d3 -size 46522 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-15-pseudo.Touch-ID-Mandatory.png b/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-15-pseudo.Touch-ID-Mandatory.png deleted file mode 100644 index 4df2c74b07..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_appLockSetupSettingsScreen-iPhone-15-pseudo.Touch-ID-Mandatory.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f976d440111790cb662bc972a55295ea77d6f6c581f69cd7a84fbeffafb4e713 -size 51879 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPad-en-GB.1.png deleted file mode 100644 index 847aaddfec..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:48fb262e42f8d01a6feeb3e4e70b72afd11e57469c87c1fb2a649e58967f0fef -size 1257762 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPad-pseudo.1.png deleted file mode 100644 index 431c408c12..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:028e7ad09b78fad84301635102b9968fb2e6d957a85f2b49a5be2d81fff0e9f3 -size 1287670 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPhone-15-en-GB.1.png deleted file mode 100644 index e647d71d07..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dc44d147264a7965e37c72ea2a9656565d5919b1fceeeb75c4bbf7aa3a320300 -size 530595 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPhone-15-pseudo.1.png deleted file mode 100644 index 9a7afc580d..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_authenticationStartScreen-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:204ba84c66920eaee46b314f64d035ce834cd08e22aaa0c9f0d0b58a6db07bd0 -size 557370 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.DM.png b/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.DM.png deleted file mode 100644 index 3a006f3b79..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.DM.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:54ef29775fd40b31a78578dfbabe1d959820441bebb93d98e95278796b278f32 -size 124304 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.Room.png b/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.Room.png deleted file mode 100644 index 8595455415..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.Room.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0e01fea50098eccd088f769862a228f157c6d841669f25f1f1069c7a3868d434 -size 142729 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.DM.png b/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.DM.png deleted file mode 100644 index 043785e36b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.DM.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5f2bd0bdf5bd80c5d95b446c3506586cef87d941053e11e326ec0aead7e6a4a5 -size 124659 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.Room.png b/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.Room.png deleted file mode 100644 index 3ca86c8814..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.Room.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:aa1f5d7f650040389a061f8e0cd1d51715bded4e147f631de212ba3720bc226f -size 144069 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-15-en-GB.DM.png b/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-15-en-GB.DM.png deleted file mode 100644 index e7255cfb3f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-15-en-GB.DM.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5458062a12859055a57f03859348658aa572d134ed6906eeff6a575f11ae52c8 -size 72837 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-15-en-GB.Room.png b/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-15-en-GB.Room.png deleted file mode 100644 index 7fe4d2ba19..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-15-en-GB.Room.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:47dfcdcfcef7152c3ccc610aa17093eac3857eddd0238590f37e1fc90d427f5d -size 87144 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-15-pseudo.DM.png b/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-15-pseudo.DM.png deleted file mode 100644 index d26f4f73ae..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-15-pseudo.DM.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cf5b48f75f09bd661480be71c3209326808f7d4e65111b29d29669143d3e7641 -size 74498 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-15-pseudo.Room.png b/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-15-pseudo.Room.png deleted file mode 100644 index 8009dcc4db..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-15-pseudo.Room.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e759b307ab44876bb4140927bf41db9484df54fc663cf4a6f778c7ff2760322f -size 91460 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPad-en-GB.1.png deleted file mode 100644 index 480edcee22..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f10187faa0870cc71be03fe91f748f4f6011f2bab7028b5e06c625eb80aa0c60 -size 134172 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPad-pseudo.1.png deleted file mode 100644 index 06325cbece..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:275663ed1e0c3d0271a1f8a0b0cd91b44b915c18782a577b49a39d58e96ae414 -size 134819 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPhone-15-en-GB.1.png deleted file mode 100644 index d72083acda..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:60cf61947b68f5a3f955d37543044136bdfe61e1d86880979296f75d03a595f7 -size 81036 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPhone-15-pseudo.1.png deleted file mode 100644 index 1745ffe2dc..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_blockedUsersScreen-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f56cd4475dbbb4b385b2e6aa5028f257e75f082b24c8d1dadf088dd999ec6ce8 -size 81615 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPad-en-GB.1.png deleted file mode 100644 index 56b317c665..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:949b617382ca9d05a57d19b1344b3666e1adb95714719ba190949a39fe915293 -size 152494 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPad-en-GB.2.png b/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPad-en-GB.2.png deleted file mode 100644 index db6f6438b6..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPad-en-GB.2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c78b8b5715b08148dd9072f55e7479bb12cee81b9829530dd338eda9059961bc -size 202139 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPad-pseudo.1.png deleted file mode 100644 index ae62a6c6db..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:81932b36dba1deb02020f8ea7fea245d494dd62b49da9c40bf8930b82d1706c4 -size 195022 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPad-pseudo.2.png b/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPad-pseudo.2.png deleted file mode 100644 index 7659df89e3..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPad-pseudo.2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c210c6effe6337247a5cedc26b00a57cb3973efe22cc0ad806e8df655af58d18 -size 241866 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPhone-15-en-GB.1.png deleted file mode 100644 index 38b20a3526..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2a7ec41d2919065925bbb052a94736cb2fd9732444e4cf29265af12bb05fa964 -size 111716 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPhone-15-en-GB.2.png b/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPhone-15-en-GB.2.png deleted file mode 100644 index e5a56a05e0..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPhone-15-en-GB.2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4a48e17f04b3451e8470fa0589a3f33c61a6b432f4b6f74e7a3cc5bf687ebeee -size 156162 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPhone-15-pseudo.1.png deleted file mode 100644 index 197b3479b5..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:73bc837836595cea34435faf3e536a45d98994b3ba8789a97f9cee7e48c38660 -size 165149 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPhone-15-pseudo.2.png b/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPhone-15-pseudo.2.png deleted file mode 100644 index 8965f4c97d..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_bugReport-iPhone-15-pseudo.2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:85edfb37bc55b45091ae64fa9ac8a7a479019d9c5edb750eb5fbb7a25019be5f -size 192028 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room-without-users.png b/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room-without-users.png deleted file mode 100644 index e42560b98f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room-without-users.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:80508da6615d27250ab96de6427d43d3ea3f45bb5bb3e8e0d44ef984eb44e885 -size 147467 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room.png b/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room.png deleted file mode 100644 index 6706320bc9..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:16b2f7a84d67037f6442612a95ec19cc1d4ac52b488a39f081798386ac9da861 -size 166799 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room-without-users.png b/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room-without-users.png deleted file mode 100644 index 1ec2f47dc9..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room-without-users.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7350cdc5f108094315699a41c57d32115cdba52505bf955c13ca17c9bebd4391 -size 174233 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room.png b/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room.png deleted file mode 100644 index 9518d6b778..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:be0a72b0680821863140ce731d8196d088ebbd699d85fa6fb894443c7a15a473 -size 195358 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPhone-15-en-GB.Create-Room-without-users.png b/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPhone-15-en-GB.Create-Room-without-users.png deleted file mode 100644 index 2183120d81..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPhone-15-en-GB.Create-Room-without-users.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a6038bcbd3a0b255d127fbac3363b56137d0d5905cb86b96454aeea69fbccd1d -size 99193 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPhone-15-en-GB.Create-Room.png b/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPhone-15-en-GB.Create-Room.png deleted file mode 100644 index 186d70061e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPhone-15-en-GB.Create-Room.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7ec9cb70cff39e08c0e1c671c97319bfda0f350590c1914b1123e66e8426b147 -size 99888 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPhone-15-pseudo.Create-Room-without-users.png b/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPhone-15-pseudo.Create-Room-without-users.png deleted file mode 100644 index 35031f0c37..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPhone-15-pseudo.Create-Room-without-users.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2d02cc1d9d00a68358d53a5d7e4138a1bbc4eb003fc92c1afb1fe455b8685715 -size 138572 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPhone-15-pseudo.Create-Room.png b/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPhone-15-pseudo.Create-Room.png deleted file mode 100644 index 68dbe3ed64..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_createRoom-iPhone-15-pseudo.Create-Room.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6db76a72596e79cd0f4a734c2dc646c2a9cb305e4e21eea380de23bf2c9ba3c7 -size 139165 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPad-en-GB.Screen.png b/PreviewTests/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPad-en-GB.Screen.png deleted file mode 100644 index 54f9d17119..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPad-en-GB.Screen.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3bb77bd8f648944e1a2ac2efc6c97a072fea26893d090d0b8999220216c1f257 -size 984477 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPad-pseudo.Screen.png b/PreviewTests/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPad-pseudo.Screen.png deleted file mode 100644 index 1837b4f973..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPad-pseudo.Screen.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8ff500bb0cee49a64535fa540eb2e42c0ea9ee11b7fab30c7b1fee9869b55d0c -size 987904 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPhone-15-en-GB.Screen.png b/PreviewTests/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPhone-15-en-GB.Screen.png deleted file mode 100644 index 21a57ab6b3..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPhone-15-en-GB.Screen.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3ce7c0aa7eab3875550cdc7694853174a01f81878346852cbe90130c03425c0d -size 36671 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPhone-15-pseudo.Screen.png b/PreviewTests/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPhone-15-pseudo.Screen.png deleted file mode 100644 index 4a470b47dd..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPhone-15-pseudo.Screen.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:608e1e592166e128873a45b57ea6e1f894222e221ceeb4a3f068bf1b6d4393d9 -size 38591 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPad-en-GB.1.png deleted file mode 100644 index d8b0fe30f9..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:97f681fac8805300e66945b3b597b55cf79dbe10aa3aca33a3f3405f981ae3bd -size 98889 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPad-pseudo.1.png deleted file mode 100644 index 38ec7ba5e1..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:614d8e886f6bd587cadaf1133a96647ede185615cf6fe4b33a75e9138f7b475c -size 113456 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPhone-15-en-GB.1.png deleted file mode 100644 index 4d9b8ee193..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c869098036009618cfd8f5e6491be8f3af6c92d60c2e8d3edc158767a671dfd1 -size 57235 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPhone-15-pseudo.1.png deleted file mode 100644 index 1e3ada23df..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetPasswordScreen-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4cd756e4bb99afbc90d2fb50fa17c766412698c768d915bd3ee828d5564f38ba -size 73637 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPad-en-GB.1.png deleted file mode 100644 index 50304ac0c8..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e125593fee18c805f9a4e44737266b17fb7673160a1da100b5b9379e6e3cb50b -size 168133 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPad-pseudo.1.png deleted file mode 100644 index f5aeaabd7c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:434146f53746a7a1bffd6483f3eb47e79bf38b1cbce86de68921391c42ac6817 -size 238287 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPhone-15-en-GB.1.png deleted file mode 100644 index bdc484c599..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:315e9644456d7221df9953dc73ec9158fb2eaa0427898155c5d79066ba7ee0ee -size 124373 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPhone-15-pseudo.1.png deleted file mode 100644 index f086b7cce8..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_encryptionResetScreen-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:93549b9921c66b937a191ff6e6dccd49f76cafb7f1e62053d1c2b4fa53d5f7b1 -size 164940 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPad-en-GB.1.png deleted file mode 100644 index d2b5c347ab..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:65281607f50cf463fc9ec3e063d7361b23e480bd49a4363371d810eace5a9f3d -size 98535 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPad-pseudo.1.png deleted file mode 100644 index d2b5c347ab..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:65281607f50cf463fc9ec3e063d7361b23e480bd49a4363371d810eace5a9f3d -size 98535 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPhone-15-en-GB.1.png deleted file mode 100644 index f9c825e511..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:112fdc4972bc77b70b5ca074e958b3f55927815074a5f6dfeb709e40b5b75ed3 -size 55344 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPhone-15-pseudo.1.png deleted file mode 100644 index f9c825e511..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:112fdc4972bc77b70b5ca074e958b3f55927815074a5f6dfeb709e40b5b75ed3 -size 55344 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-en-GB.Bloom.png b/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-en-GB.Bloom.png deleted file mode 100644 index a26422be18..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-en-GB.Bloom.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f50d519a52f2e49cdedcb1eacef0af4edb451967a307f278e82e285639f9a23a -size 1920727 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-en-GB.Gradient.png b/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-en-GB.Gradient.png deleted file mode 100644 index ed7f79d6ae..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-en-GB.Gradient.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3c66ef30b834c02c20cf56f4af0845ff297333aef667d1ba00e2c2ffe60c2042 -size 548640 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-en-GB.Plain.png b/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-en-GB.Plain.png deleted file mode 100644 index 38304a161a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-en-GB.Plain.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b8591e88af4429560dd81d282def3a12c3a08a615bbade1c98d3bc49ccf8913e -size 118308 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-pseudo.Bloom.png b/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-pseudo.Bloom.png deleted file mode 100644 index b3926c393a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-pseudo.Bloom.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:322145c0759512ad278e427d1beea077d1ef4e9f2b7d9c0da4dd36cf9d1b8d10 -size 1940800 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-pseudo.Gradient.png b/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-pseudo.Gradient.png deleted file mode 100644 index 15dd9ef3fb..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-pseudo.Gradient.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6fc338f2393786439f741d91cfc5544097420cc7e2ee0e628cb8878842a8dbcf -size 567667 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-pseudo.Plain.png b/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-pseudo.Plain.png deleted file mode 100644 index 14a077315b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPad-pseudo.Plain.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9697a27934b44b49d35a28c96910c4e7422a128c5b50e476a6ff7d35568cc829 -size 124622 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-15-en-GB.Bloom.png b/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-15-en-GB.Bloom.png deleted file mode 100644 index e741257a61..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-15-en-GB.Bloom.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:30d5802cab78c046ff9bf579636900801c0519346073c425934a2b47be5ea770 -size 779169 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-15-en-GB.Gradient.png b/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-15-en-GB.Gradient.png deleted file mode 100644 index 25c3ce443e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-15-en-GB.Gradient.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3a1f2f0f2ca8a29d6b9d6885b7da08d090bab305ae1334a91d3c6cfcae04b624 -size 347517 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-15-en-GB.Plain.png b/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-15-en-GB.Plain.png deleted file mode 100644 index 1e0af43e92..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-15-en-GB.Plain.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2cc0b66675bb480d816d69cfaf74cf123bc5b403569ca85bddee7ea5d5a885eb -size 72202 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-15-pseudo.Bloom.png b/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-15-pseudo.Bloom.png deleted file mode 100644 index 3954ed283b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-15-pseudo.Bloom.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:41cb3b96d8f574ed358a4cb0211d54152df5ece8970d45075f0e4076e97e15cf -size 802262 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-15-pseudo.Gradient.png b/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-15-pseudo.Gradient.png deleted file mode 100644 index 8394a851d2..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-15-pseudo.Gradient.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:828bf97162c229f590f6156666a63fdd9f5f4346ed0862ec3cecf51f2f1a6591 -size 367824 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-15-pseudo.Plain.png b/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-15-pseudo.Plain.png deleted file mode 100644 index f71ca83c1a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_fullscreenDialog-iPhone-15-pseudo.Plain.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5db2dc5f30bd902ae67b197fe50442e934058ae63cdef8d5eb0f520a5a4d08b7 -size 88712 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_globalSearchScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_globalSearchScreen-iPad-en-GB.1.png deleted file mode 100644 index 0281341e7c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_globalSearchScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d16dfb8ec6fd9a7e0bd723c5b77ee0d6ad1bb438522bcd15daca90a8f95ce74a -size 153926 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_globalSearchScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_globalSearchScreen-iPad-pseudo.1.png deleted file mode 100644 index 549b905336..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_globalSearchScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bb77d8061dc9dd49f1a3e29e63c3bdd9bef52814886907f14c523551b43209ae -size 154357 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_heroImage-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_heroImage-iPad-en-GB.1.png deleted file mode 100644 index 07973ed32a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_heroImage-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5aff3c2bdc10d469661d8d156619b7a638aa5db4bff2525ea1a7091753e13194 -size 75111 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_heroImage-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_heroImage-iPad-pseudo.1.png deleted file mode 100644 index 07973ed32a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_heroImage-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5aff3c2bdc10d469661d8d156619b7a638aa5db4bff2525ea1a7091753e13194 -size 75111 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_heroImage-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_heroImage-iPhone-15-en-GB.1.png deleted file mode 100644 index 9e910808da..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_heroImage-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b44ce499b27688bbf5dee93b8be232bc1956f764b6056bb9d018f4642ba802b9 -size 33871 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_heroImage-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_heroImage-iPhone-15-pseudo.1.png deleted file mode 100644 index 9e910808da..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_heroImage-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b44ce499b27688bbf5dee93b8be232bc1956f764b6056bb9d018f4642ba802b9 -size 33871 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPad-en-GB.Layout.png b/PreviewTests/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPad-en-GB.Layout.png deleted file mode 100644 index 7be2c1453b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPad-en-GB.Layout.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:22818ad5c9187465321fd0a4705ddbab3a26c730c5c35c9a60aee08e4b9c9732 -size 277085 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPad-pseudo.Layout.png b/PreviewTests/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPad-pseudo.Layout.png deleted file mode 100644 index 7be2c1453b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPad-pseudo.Layout.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:22818ad5c9187465321fd0a4705ddbab3a26c730c5c35c9a60aee08e4b9c9732 -size 277085 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPhone-15-en-GB.Layout.png b/PreviewTests/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPhone-15-en-GB.Layout.png deleted file mode 100644 index 0854910e37..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPhone-15-en-GB.Layout.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5f4bd9f85056dc6a84554f5971343d7500f1e45925e54ce99ebcd91021dce7b4 -size 243420 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPhone-15-pseudo.Layout.png b/PreviewTests/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPhone-15-pseudo.Layout.png deleted file mode 100644 index 0854910e37..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_highlightedTimelineItemModifier-iPhone-15-pseudo.Layout.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5f4bd9f85056dc6a84554f5971343d7500f1e45925e54ce99ebcd91021dce7b4 -size 243420 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Empty.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Empty.png deleted file mode 100644 index 62cb6459aa..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Empty.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c842b03844cf8ecc0cb5b6925b1124d58e74a097393d0e54e4a6415f1b51f9bf -size 114086 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Loaded.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Loaded.png deleted file mode 100644 index 615be157b3..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Loaded.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:686f15681b9b6c0dc437f5fa2832ee83272f0dfb6a81d1429c8e629a7bceefab -size 249090 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Loading.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Loading.png deleted file mode 100644 index 113df4ffe9..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Loading.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f6863423dba8d98e8e8a3cfa18f71ace637addac09fedce8412df9c47ad08923 -size 92239 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Empty.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Empty.png deleted file mode 100644 index d9597a384e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Empty.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7a6bf32618c6df5702936d6cd56f031f3e90797621e0c2970b977844535219ff -size 123860 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Loaded.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Loaded.png deleted file mode 100644 index d2745f6f8f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Loaded.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:289e097c870f4feb95855c4895211585b364647b8b92a2f83da609a7ee49fca0 -size 256877 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Loading.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Loading.png deleted file mode 100644 index f5888a8590..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Loading.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:38ed6dcecbb9d7b6bb6300441655ae83305fac2e52d05ca30d4373e521902f38 -size 92962 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-en-GB.Empty.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-en-GB.Empty.png deleted file mode 100644 index 4b668c91cb..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-en-GB.Empty.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:09d96836a64d59f6822701bcf4382bbe4d68b856133c6d1c6821712686f4ad0b -size 51171 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-en-GB.Loaded.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-en-GB.Loaded.png deleted file mode 100644 index f0dad7880e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-en-GB.Loaded.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:38344dcbf240f85d2210b1edbd5f9b840122a0b79b3bfdf136306105c5085f44 -size 178099 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-en-GB.Loading.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-en-GB.Loading.png deleted file mode 100644 index 426ac844c3..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-en-GB.Loading.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5ba2012b4a967088afd7487d12c9f7bc6bb562f92b573565a7c4cebafc4f6483 -size 50413 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-pseudo.Empty.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-pseudo.Empty.png deleted file mode 100644 index 1543a95496..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-pseudo.Empty.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fa06f67c175c2ac4c307691211a88b7e624e8dcfc85226cb3ec5c617f1c57830 -size 52042 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-pseudo.Loaded.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-pseudo.Loaded.png deleted file mode 100644 index 1deffefc34..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-pseudo.Loaded.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6629655cd250a07ee2a0ddcbf29517c1972c715dfdf4874e7d9e015f575138b5 -size 180703 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-pseudo.Loading.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-pseudo.Loading.png deleted file mode 100644 index 50c3101e96..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreen-iPhone-15-pseudo.Loading.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:99fe6c2b13c37b439fe269c3fb2bf05fa00c6f62cbc3ecd986e0293ae9877c1e -size 51302 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-en-GB.Constrained-layout.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-en-GB.Constrained-layout.png deleted file mode 100644 index 0bc1ab7817..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-en-GB.Constrained-layout.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9d95ec9814539ac8e198435f176c8cb8569230102c2b06ccb77858c3ab2ad51b -size 131915 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-en-GB.Normal-Layout.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-en-GB.Normal-Layout.png deleted file mode 100644 index b268a5d70e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-en-GB.Normal-Layout.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c37f4470d6234c8bf3ec971e985ef8ca711ace205b8ec4cfa7b21ac5a4096264 -size 100440 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-pseudo.Constrained-layout.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-pseudo.Constrained-layout.png deleted file mode 100644 index 9e8139e098..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-pseudo.Constrained-layout.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3af6a3390378d32731502abf3a7e4d5289644dc17fe3baaa110f81043f581f7a -size 147760 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-pseudo.Normal-Layout.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-pseudo.Normal-Layout.png deleted file mode 100644 index 934cfcf7be..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPad-pseudo.Normal-Layout.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a2a1b2494b8308206208f02d720b10dd00782dda2a2c21d0c490efba291bf0f0 -size 107707 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-15-en-GB.Constrained-layout.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-15-en-GB.Constrained-layout.png deleted file mode 100644 index 9892d2f37e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-15-en-GB.Constrained-layout.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:caf7a56b6c22716cdfd0d3e832d68d9e6a4536260cdea1257a9d4d4b781e1360 -size 89052 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-15-en-GB.Normal-Layout.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-15-en-GB.Normal-Layout.png deleted file mode 100644 index db3cfb2452..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-15-en-GB.Normal-Layout.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0945536df512300976d1f68174b2b16daf61e8fa28196bcff35378a47e366353 -size 59869 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-15-pseudo.Constrained-layout.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-15-pseudo.Constrained-layout.png deleted file mode 100644 index a75a2fe45e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-15-pseudo.Constrained-layout.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:28dd6da78c585350bbdaeff25e03fde6df44fcc52a8902bd431e11cd881db9b8 -size 131944 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-15-pseudo.Normal-Layout.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-15-pseudo.Normal-Layout.png deleted file mode 100644 index e00f2deced..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenEmptyStateView-iPhone-15-pseudo.Normal-Layout.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6d158af40e754698a55755a78728b307e97e0bae7cd035dcbad4c6fec453c859 -size 83625 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPhone-15-pseudo.1.png deleted file mode 100644 index 74575e2bc9..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ab63620535fac952a0fad199e57ff12eddfcd18dc985b184e017b66ce158e478 -size 193338 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRecoveryKeyConfirmationBanner-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRecoveryKeyConfirmationBanner-iPhone-15-en-GB.1.png deleted file mode 100644 index 6827c0e07a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRecoveryKeyConfirmationBanner-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:716bad3c838e466a27343c2983edead0ff537639b12d17ee0b10059854fea183 -size 58465 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRecoveryKeyConfirmationBanner-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRecoveryKeyConfirmationBanner-iPhone-15-pseudo.1.png deleted file mode 100644 index fef2119bda..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRecoveryKeyConfirmationBanner-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6b4947f12b70aff7d5291fe0d5d419628cbc42dcae65c34116eed2b2b9777e90 -size 79752 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-en-GB.Generic.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-en-GB.Generic.png deleted file mode 100644 index cbe30345bd..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-en-GB.Generic.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0a4145fcf322881e1557ed5b723a3b73a1379ff57332bc1cc53a8d9b90ac0fe7 -size 221122 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-pseudo.Generic.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-pseudo.Generic.png deleted file mode 100644 index cbe30345bd..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-pseudo.Generic.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0a4145fcf322881e1557ed5b723a3b73a1379ff57332bc1cc53a8d9b90ac0fe7 -size 221122 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-15-en-GB.Generic.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-15-en-GB.Generic.png deleted file mode 100644 index c8ad42b1b3..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-15-en-GB.Generic.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3a392c4dc3d9e7ea90f6e4bca1ae12cd4556c95ba15ae337bfe064ce1797872e -size 161993 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-15-pseudo.Generic.png b/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-15-pseudo.Generic.png deleted file mode 100644 index c8ad42b1b3..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-15-pseudo.Generic.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3a392c4dc3d9e7ea90f6e4bca1ae12cd4556c95ba15ae337bfe064ce1797872e -size 161993 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPad-en-GB.1.png deleted file mode 100644 index 9bd9deb9b5..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bf60b748aa8c48aad659c3567c814cc1f601c194fbafcfffeed37fe6f3594e40 -size 108900 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPad-pseudo.1.png deleted file mode 100644 index 99fe3cac32..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:080f9960d7ca7e83a183050cc663c50635a7a6260bcfd808cf7607680cbf7ae4 -size 123013 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPhone-15-en-GB.1.png deleted file mode 100644 index 7fa28b5f8b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:797ad10083353eeb2362f882ff1072a213dde5c879511e5854c4aa415f68d35e -size 64174 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPhone-15-pseudo.1.png deleted file mode 100644 index f17402a1ec..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmationScreen-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e0d54f1544f9cd0ffc14183a8baff1317fd0c793ca94c7e88e8a0a2d02816b36 -size 81854 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmedScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmedScreen-iPad-en-GB.1.png deleted file mode 100644 index 6683c4f5f7..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmedScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:208ab94952b2cbe0f1dfdd04add85792f35168cbedeb76f3e209efd78a4a9006 -size 94849 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmedScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmedScreen-iPad-pseudo.1.png deleted file mode 100644 index 6a4c7e00a0..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_identityConfirmedScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0d26fabbe645773881e5b5228a112871b30a52acd36ee300e15d70cc56b56b23 -size 108455 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPad-en-GB.1.png deleted file mode 100644 index 91467ebe21..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ec3b4d8dbd25c91790ca8a220c5d0d848dbc2e82668070ba4e1649990ba4d598 -size 462017 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPad-pseudo.1.png deleted file mode 100644 index 91467ebe21..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ec3b4d8dbd25c91790ca8a220c5d0d848dbc2e82668070ba4e1649990ba4d598 -size 462017 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPhone-15-en-GB.1.png deleted file mode 100644 index ef24497c70..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:63011572252e6377c8d7717c1623e2b733b38fb95a469718d8f8f75c4e622148 -size 388241 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPhone-15-pseudo.1.png deleted file mode 100644 index ef24497c70..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:63011572252e6377c8d7717c1623e2b733b38fb95a469718d8f8f75c4e622148 -size 388241 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPad-en-GB.1.png deleted file mode 100644 index b7ad9b9dba..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:02699cd07649387e2da2c18b0b3c25a3344b39bc58bcae129e4bfad4760bdd82 -size 86562 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPad-pseudo.1.png deleted file mode 100644 index 9bb5dc03f2..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:61728a7bba441a19683a2da075ae7bbc306d6862e3f4e83099e601d78d442491 -size 89079 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPhone-15-en-GB.1.png deleted file mode 100644 index 88882cf12e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e4578eee2444f73650e68f79142d5403a3649ee865307f8f08499b08e3ea0e44 -size 41171 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPhone-15-pseudo.1.png deleted file mode 100644 index 9bc8f7db40..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1d11723c8fd5a8516658f08bd82016a8a27ab673d2c3996fa42d1378dd7336f0 -size 43313 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPad-en-GB.1.png deleted file mode 100644 index 978aba7540..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:541cfb97fea99904f6ebd8834e113abd10452e1278833387ec7c47d5a52648e0 -size 82037 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPad-pseudo.1.png deleted file mode 100644 index 978aba7540..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:541cfb97fea99904f6ebd8834e113abd10452e1278833387ec7c47d5a52648e0 -size 82037 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPhone-15-en-GB.1.png deleted file mode 100644 index 0c9697f520..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c809f47f4ba7c478d57835776b496e77d47bf7b8997c2f113f045ae19c910939 -size 40862 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPhone-15-pseudo.1.png deleted file mode 100644 index 0c9697f520..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_inviteUsersScreenSelectedItem-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c809f47f4ba7c478d57835776b496e77d47bf7b8997c2f113f045ae19c910939 -size 40862 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Invite.png b/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Invite.png deleted file mode 100644 index 57f5cd7ef8..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Invite.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ff22a5528ff2c3df3d16f8340919a8b31117603d374db7531d26021c774d3512 -size 1980756 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Join.png b/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Join.png deleted file mode 100644 index e33772658b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Join.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:656011b2f47a26f568bf84df3ccd5c14281722a9102bf8b3b79b714c22c26b21 -size 1944766 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knock.png b/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knock.png deleted file mode 100644 index a193b68889..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knock.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:29ba90bb910486c5aba146e7f6692975d76adbde4c7aa291ada4164291726848 -size 1936891 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Unknown.png b/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Unknown.png deleted file mode 100644 index 7967de20fe..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Unknown.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:682a385d77654a834eda1e16b05ceae250a9730868b133f5d73e0656b7d8e1f4 -size 1893025 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invite.png b/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invite.png deleted file mode 100644 index 31bc3567e3..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invite.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0cfe8c8a252ff738c7f630d083e5da55717027c01b21bf7c296346516fcc4650 -size 1983322 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Join.png b/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Join.png deleted file mode 100644 index c2734a93a1..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Join.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c091decb9974de8d19b018e19285428fc5c5ee13c4706347c08b1338724db372 -size 1946457 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knock.png b/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knock.png deleted file mode 100644 index f31e44885c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knock.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:de02b3401e0343c7784e8b29f8a255c4eafaf47574f55fdf518cf3578cd966a5 -size 1938644 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Unknown.png b/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Unknown.png deleted file mode 100644 index 7f22e0b186..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Unknown.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5919ca74ce5a73c50b1ade86ce92cd6043d4aa187157be648b2a609f12546256 -size 1898227 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-en-GB.Invite.png b/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-en-GB.Invite.png deleted file mode 100644 index d24a6db3fc..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-en-GB.Invite.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f3ebfa2fc96c65b8652344cb46cf33f3c546f3f84e74d8b3403be8aebccb9972 -size 818046 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-en-GB.Join.png b/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-en-GB.Join.png deleted file mode 100644 index 73f82631be..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-en-GB.Join.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f08cb674179dc0ad5765865043e1d93dc5f9612669e15c702b8c7121cbe110d7 -size 796666 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-en-GB.Knock.png b/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-en-GB.Knock.png deleted file mode 100644 index d83d9d41d4..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-en-GB.Knock.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5ef205a1f5a1756ba3f89b8c0dd2dcfccb39da7e5bc1e72abd90fd2a3d803812 -size 791829 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-pseudo.Invite.png b/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-pseudo.Invite.png deleted file mode 100644 index 3eb0b72518..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-pseudo.Invite.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:58a83d3709c4e7d6ac704ebb46b400e4127e97b91d7a13e5a5c0ab45df214827 -size 820433 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-pseudo.Join.png b/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-pseudo.Join.png deleted file mode 100644 index 1aaa9604dc..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-pseudo.Join.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:24751938068a6a8a711d083640911f0b0d0a7a2d46e9c0cb649804a89e850e88 -size 798431 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-pseudo.Knock.png b/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-pseudo.Knock.png deleted file mode 100644 index c714c94212..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-15-pseudo.Knock.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4e8df72dbca5c057ce933d2602d5e29350a3af0e79f6c1431b6cee897030e56d -size 793487 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.Credentials-Entered.png b/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.Credentials-Entered.png deleted file mode 100644 index f04cf8d22b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.Credentials-Entered.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0b53aff4e0cb1d0a3f595fb7f79a5e5806f8593c96b09938792054669a5af8f0 -size 94857 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.OIDC-Fallback.png b/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.OIDC-Fallback.png deleted file mode 100644 index ecbe740f22..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.OIDC-Fallback.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d9015423d13b18ccedfad0d8c17e748ae66877b4cfe3d6869ef537a8889d6968 -size 98431 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.Unsupported.png b/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.Unsupported.png deleted file mode 100644 index ecbe740f22..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.Unsupported.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d9015423d13b18ccedfad0d8c17e748ae66877b4cfe3d6869ef537a8889d6968 -size 98431 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.matrix-org.png b/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.matrix-org.png deleted file mode 100644 index ecbe740f22..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.matrix-org.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d9015423d13b18ccedfad0d8c17e748ae66877b4cfe3d6869ef537a8889d6968 -size 98431 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.Credentials-Entered.png b/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.Credentials-Entered.png deleted file mode 100644 index 3fc0314635..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.Credentials-Entered.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d5d476e6d61cf614c54dadf3fe8fa4178530130132b15e660f8cdcc361749996 -size 101926 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.OIDC-Fallback.png b/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.OIDC-Fallback.png deleted file mode 100644 index 078d06929a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.OIDC-Fallback.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9e844abeb590cfc4340b6b91a49ec0c9b3c1de9a0b012c71567d6f0196e8b5da -size 107238 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.Unsupported.png b/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.Unsupported.png deleted file mode 100644 index 078d06929a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.Unsupported.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9e844abeb590cfc4340b6b91a49ec0c9b3c1de9a0b012c71567d6f0196e8b5da -size 107238 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.matrix-org.png b/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.matrix-org.png deleted file mode 100644 index 078d06929a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.matrix-org.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9e844abeb590cfc4340b6b91a49ec0c9b3c1de9a0b012c71567d6f0196e8b5da -size 107238 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPad-en-GB.1.png deleted file mode 100644 index c3212bf37d..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:01bcbaf198c7a6aeede8a326bd9c6a3e46dd0c3b689787a968e94bb4621192a6 -size 107912 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPad-pseudo.1.png deleted file mode 100644 index 5e74cfdbb6..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:937a959a3d594fe1e5a2f2c44577d738d0bab4d8daed28e20af798c134e195f2 -size 108538 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPhone-15-en-GB.1.png deleted file mode 100644 index 4a7065502f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:330ccf57981cd8469dc6229251dfa51ab73bb1e85c352c6b84806da0b02f1765 -size 67941 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPhone-15-pseudo.1.png deleted file mode 100644 index c4e74d8bad..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c718ad9266b37f6169e7a646a6ae42757999aba4e22c86aa740e084629c4bd2b -size 68628 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPad-en-GB.1.png deleted file mode 100644 index 673b73de9a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2275b7e9e260b776eab0d1153458c0696c2fcb7abf2ee8b4be2237b080e0af8d -size 69739 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPad-pseudo.1.png deleted file mode 100644 index 09b3a2702c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:42742ec1667f406c02a5f6018dc8b4bbf5910dfe90597aecc35534350de5b29f -size 70083 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPhone-15-en-GB.1.png deleted file mode 100644 index 803c14d358..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:707ce516e4e6e8180b733cbfde1eaf26bd5c62695a6ddfc9904365dab9f8dcd0 -size 29302 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPhone-15-pseudo.1.png deleted file mode 100644 index 3ce225b88c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_matrixUserPermalink-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:af83def35f61981d8fa89dff9db212ec7934ad9dd17bb2bc2346974433ca7342 -size 30057 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPad-en-GB.1.png deleted file mode 100644 index df82253adb..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e4a44f0f7c645759ec03e933523e6a03b63e7cde2f65ae0457821853c6b64e04 -size 152820 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPad-pseudo.1.png deleted file mode 100644 index e8ed6cc26d..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d588a94ddd7fe167093ed7fb1175c6b61fbb38b817a94acee2e6c47c868122d6 -size 154590 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPhone-15-en-GB.1.png deleted file mode 100644 index 248e2acf3d..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:eebe2c0c5a6550bd71164c457c9bb4d3dbf8f2524d8b4e7b190ec8b7cc237cc3 -size 101869 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPhone-15-pseudo.1.png deleted file mode 100644 index efe26c0644..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0d092bc39ace8a20609aa6879829748aa01d2564049b6069681f5d366eeab128 -size 101815 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.Custom-Attachment.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.Custom-Attachment.png deleted file mode 100644 index dfdb29847f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.Custom-Attachment.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b17b6bff7c89b5c6df8b03854ba21bc46bea39cc8b07b95ee01fe2bd967af5d1 -size 72246 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.Custom-Text.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.Custom-Text.png deleted file mode 100644 index a1b141723f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.Custom-Text.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9a75d59600d7aed8ea9bcdb3af161cf5556f928471fc8d27162dae66f279dde9 -size 75081 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.SwiftUI-Default-Text.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.SwiftUI-Default-Text.png deleted file mode 100644 index fec80eef62..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.SwiftUI-Default-Text.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e6d20bd0b55ca91d3f8fdcb34369335681e6111f5f7690f0fbef8da106efc94d -size 75081 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.With-block-quote.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.With-block-quote.png deleted file mode 100644 index baa7f6d42a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.With-block-quote.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:48e0851e138b34aedaee6815decb142765a8ceba072b894001caed8b058b59e2 -size 92959 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.With-list.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.With-list.png deleted file mode 100644 index 30e1ac285e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-en-GB.With-list.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:42c180433c3f4edf87901c2b2bf487a6f64767ef191df263d9f616a8f1d3414a -size 79612 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.Custom-Attachment.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.Custom-Attachment.png deleted file mode 100644 index dfdb29847f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.Custom-Attachment.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b17b6bff7c89b5c6df8b03854ba21bc46bea39cc8b07b95ee01fe2bd967af5d1 -size 72246 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.Custom-Text.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.Custom-Text.png deleted file mode 100644 index a1b141723f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.Custom-Text.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9a75d59600d7aed8ea9bcdb3af161cf5556f928471fc8d27162dae66f279dde9 -size 75081 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.SwiftUI-Default-Text.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.SwiftUI-Default-Text.png deleted file mode 100644 index fec80eef62..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.SwiftUI-Default-Text.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e6d20bd0b55ca91d3f8fdcb34369335681e6111f5f7690f0fbef8da106efc94d -size 75081 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.With-block-quote.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.With-block-quote.png deleted file mode 100644 index baa7f6d42a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.With-block-quote.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:48e0851e138b34aedaee6815decb142765a8ceba072b894001caed8b058b59e2 -size 92959 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.With-list.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.With-list.png deleted file mode 100644 index 30e1ac285e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPad-pseudo.With-list.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:42c180433c3f4edf87901c2b2bf487a6f64767ef191df263d9f616a8f1d3414a -size 79612 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-en-GB.Custom-Attachment.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-en-GB.Custom-Attachment.png deleted file mode 100644 index 8c66657bd8..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-en-GB.Custom-Attachment.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b8f83d9f010d9892c3cc50ae8d6f053dd238ec4450f0767b88739298b1644ee1 -size 31470 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-en-GB.Custom-Text.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-en-GB.Custom-Text.png deleted file mode 100644 index 3cafa6dfba..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-en-GB.Custom-Text.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bfac20296c3edfeff34de7c8293115698d760db7784dc30bdaf53918a37ee0e1 -size 42755 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-en-GB.SwiftUI-Default-Text.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-en-GB.SwiftUI-Default-Text.png deleted file mode 100644 index 531b477096..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-en-GB.SwiftUI-Default-Text.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:58ff39ed68d2c5b5c7d17ecb2dc458ecc591896716829f1677cec3b2ee4ab19f -size 42757 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-en-GB.With-block-quote.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-en-GB.With-block-quote.png deleted file mode 100644 index a9954ae055..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-en-GB.With-block-quote.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3a0b20a9b91736659c58ea42ef6e6a127d7525a5f3d20f895fd9633138fd4136 -size 54599 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-en-GB.With-list.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-en-GB.With-list.png deleted file mode 100644 index 9513c15377..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-en-GB.With-list.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4f994f0b8718cdcf731e638b521b386efede7bcabb0f0b5178bd3313d7f92ca4 -size 38972 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-pseudo.Custom-Attachment.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-pseudo.Custom-Attachment.png deleted file mode 100644 index 8c66657bd8..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-pseudo.Custom-Attachment.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b8f83d9f010d9892c3cc50ae8d6f053dd238ec4450f0767b88739298b1644ee1 -size 31470 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-pseudo.Custom-Text.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-pseudo.Custom-Text.png deleted file mode 100644 index 3cafa6dfba..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-pseudo.Custom-Text.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bfac20296c3edfeff34de7c8293115698d760db7784dc30bdaf53918a37ee0e1 -size 42755 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-pseudo.SwiftUI-Default-Text.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-pseudo.SwiftUI-Default-Text.png deleted file mode 100644 index 531b477096..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-pseudo.SwiftUI-Default-Text.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:58ff39ed68d2c5b5c7d17ecb2dc458ecc591896716829f1677cec3b2ee4ab19f -size 42757 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-pseudo.With-block-quote.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-pseudo.With-block-quote.png deleted file mode 100644 index a9954ae055..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-pseudo.With-block-quote.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3a0b20a9b91736659c58ea42ef6e6a127d7525a5f3d20f895fd9633138fd4136 -size 54599 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-pseudo.With-list.png b/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-pseudo.With-list.png deleted file mode 100644 index 9513c15377..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_messageText-iPhone-15-pseudo.With-list.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4f994f0b8718cdcf731e638b521b386efede7bcabb0f0b5178bd3313d7f92ca4 -size 38972 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-en-GB.1.png deleted file mode 100644 index 0d6ea4ae42..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cc855ff09e229c2a64323f8c7238df40da0d1158e24fc124117c47feee25f78e -size 145410 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-en-GB.Configuration-mismatch.png b/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-en-GB.Configuration-mismatch.png deleted file mode 100644 index 04259cdadf..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-en-GB.Configuration-mismatch.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1bdd8bb453dd6c631ff964d638b4b504b26df7694f02f359760c9d7db990dbd3 -size 117402 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-pseudo.1.png deleted file mode 100644 index 921b3849cf..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:625eaa4d499ac129b44286e798c91413ab23b466bd2a168e6fe120e5576e5720 -size 164303 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-pseudo.Configuration-mismatch.png b/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-pseudo.Configuration-mismatch.png deleted file mode 100644 index 619367324d..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPad-pseudo.Configuration-mismatch.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:03989b477e33548dfbb2ef48b6b91f8eadae5008052b9525c730808ebeeff75d -size 145292 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-15-en-GB.1.png deleted file mode 100644 index f50b1daef2..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e6fec1dc6f5da74da57f299469e3f1c67b31ecd6915d8ac308bf95a91f5735b5 -size 91729 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-15-en-GB.Configuration-mismatch.png b/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-15-en-GB.Configuration-mismatch.png deleted file mode 100644 index 0f5c4a4042..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-15-en-GB.Configuration-mismatch.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e1bff4e6e78202903112b026413426c505f3f6ad44c04287443a70eb2029ba65 -size 72109 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-15-pseudo.1.png deleted file mode 100644 index fa8850b58c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8e3484f1b326ee435eb1207e20007308bd35fa1bb0a900b7befd776bb214d78e -size 125998 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-15-pseudo.Configuration-mismatch.png b/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-15-pseudo.Configuration-mismatch.png deleted file mode 100644 index 0b511869ae..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-15-pseudo.Configuration-mismatch.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4962a12a8268725ca9609d8307a8c4096f78f5ac67115b5deefe8242020570ed -size 109210 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPad-en-GB.1.png deleted file mode 100644 index be41d5dd75..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ff57d03207c8349bd1d52a67b1e5198bbdd7c9c736779b2142a4badee5209f68 -size 108135 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPad-pseudo.1.png deleted file mode 100644 index be41d5dd75..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ff57d03207c8349bd1d52a67b1e5198bbdd7c9c736779b2142a4badee5209f68 -size 108135 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPhone-15-en-GB.1.png deleted file mode 100644 index 1dd4cc4a1c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4be47062f28fe77f3b2ce53b815a2a0f1c5b8af7fe5884915c5fe93d02014fc8 -size 65482 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPhone-15-pseudo.1.png deleted file mode 100644 index 1dd4cc4a1c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4be47062f28fe77f3b2ce53b815a2a0f1c5b8af7fe5884915c5fe93d02014fc8 -size 65482 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPad-en-GB.1.png deleted file mode 100644 index 576e6a0473..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:792b9704be2c179392b93540fd3efd20697921f1fa9979bd9c6297ab180e7d6e -size 95185 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPad-pseudo.1.png deleted file mode 100644 index 2695fab3f5..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fa12b52b37641df2270df083d64a8266212b4d95960e70b052a002baef129201 -size 109865 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPhone-15-en-GB.1.png deleted file mode 100644 index 769207d653..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c520c10a03670bcf1a84cb2521a402a076cd6edd27fc32efffb8da955c159824 -size 56615 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPhone-15-pseudo.1.png deleted file mode 100644 index 9618a50532..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedEventsTimelineScreen-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:57970025bc4c1ed70433696bac8bc18afd57fda4c6f96b538a0bb322946dfdb2 -size 76367 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPad-en-GB.1.png deleted file mode 100644 index 22b97c881f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:52a543349c38a46a7abf42d9f5b83aed47b40621e358fe63b98487acff03b461 -size 147075 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPad-pseudo.1.png deleted file mode 100644 index 40030d446f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:131dadbb128453abb744bd49c2cd592bbd9f0f5bdee5ba6ea71f541a10ee70ee -size 182373 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPhone-15-en-GB.1.png deleted file mode 100644 index 59dcea9a6a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ade81f08af5344aab81fdebbffe27a4b04976ce8e3cc8f397d5328c51998ad09 -size 91413 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPhone-15-pseudo.1.png deleted file mode 100644 index fcd8c4da61..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:919e3df86ce263d06f479c701b6981a66b0d6217e13cf3cff12445b9c6a24d77 -size 106938 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPad-en-GB.1.png deleted file mode 100644 index 3a447d926e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:79651ee8761ee753217cec2b76146a00bc7e3ca962d05050aa36a678b164687c -size 12283 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPad-pseudo.1.png deleted file mode 100644 index e524a30bbf..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6ad49022cc1bbe83af7b9361a5d9f5919d7d1ec81c21a105eb7a12f063913555 -size 16147 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPhone-15-en-GB.1.png deleted file mode 100644 index db26065a4d..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7d1e40829a9ae597796b0d9cbbcb5b6849396a18046e82dd0b0c46547d6db415 -size 8795 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPhone-15-pseudo.1.png deleted file mode 100644 index b949859ad7..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsIndicatorView-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c876c09a58ccf08a46cd597d3dec97a17bc422358ebec26bb10f76edd7417a8f -size 15316 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-en-GB.Split-View.png b/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-en-GB.Split-View.png deleted file mode 100644 index 696c0a103f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-en-GB.Split-View.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dd60127c666c61cdfaf82e6ba5386ae9222c88fea3c07c47ee8cef2a01103031 -size 214888 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-en-GB.With-background.png b/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-en-GB.With-background.png deleted file mode 100644 index 3674b4a1b4..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-en-GB.With-background.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1971c6c83b69d3bcbb9a0534c5a71454f5419c1ee785bfe27cd04139fe885456 -size 1437284 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-pseudo.Split-View.png b/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-pseudo.Split-View.png deleted file mode 100644 index 696c0a103f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-pseudo.Split-View.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dd60127c666c61cdfaf82e6ba5386ae9222c88fea3c07c47ee8cef2a01103031 -size 214888 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-pseudo.With-background.png b/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-pseudo.With-background.png deleted file mode 100644 index 3674b4a1b4..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPad-pseudo.With-background.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1971c6c83b69d3bcbb9a0534c5a71454f5419c1ee785bfe27cd04139fe885456 -size 1437284 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-15-en-GB.Split-View.png b/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-15-en-GB.Split-View.png deleted file mode 100644 index f47c8e37ac..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-15-en-GB.Split-View.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ca1ad1be10250c0bf9bc811726b94551fbc9deaec8b10ea93d8343da99b01573 -size 28278 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-15-pseudo.Split-View.png b/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-15-pseudo.Split-View.png deleted file mode 100644 index f47c8e37ac..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_placeholderScreen-iPhone-15-pseudo.Split-View.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ca1ad1be10250c0bf9bc811726b94551fbc9deaec8b10ea93d8343da99b01573 -size 28278 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-en-GB.Edit.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-en-GB.Edit.png deleted file mode 100644 index 0af7756ab3..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-en-GB.Edit.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4bb8120e7159d365cc5191ae9c68acc7abf119775e5a889978615d1b82c09c48 -size 120893 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-en-GB.New.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-en-GB.New.png deleted file mode 100644 index b31ed531c6..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-en-GB.New.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:91002c10db64097b88052028d80049128e9042597bffccfcfd3871d45bcc9683 -size 122064 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-pseudo.Edit.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-pseudo.Edit.png deleted file mode 100644 index 2c7a790655..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-pseudo.Edit.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4f10c4514e20619f8ec2e22722cd8156cdf87a0733c9c7690047e5ec28c0bbb0 -size 126581 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-pseudo.New.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-pseudo.New.png deleted file mode 100644 index ebb337d099..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-pseudo.New.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8a8b23dba1741852454a25712583a7f018dee1af2c142269a245a87d0338a11d -size 132162 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-15-en-GB.Edit.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-15-en-GB.Edit.png deleted file mode 100644 index 96f023e664..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-15-en-GB.Edit.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ecb882116531c6f242e2b404263bd709a49abd4ead6038a1a6737c4a4c933ac9 -size 73200 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-15-en-GB.New.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-15-en-GB.New.png deleted file mode 100644 index b684b02467..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-15-en-GB.New.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0b1684faa72eb27755a77239284e639f3d74afcaea63e266d13ff187dac58f56 -size 71576 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-15-pseudo.Edit.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-15-pseudo.Edit.png deleted file mode 100644 index fe7173d550..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-15-pseudo.Edit.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1888bbf6a80158c7dd7c9d31442d7c8a17729184e8a963cf6bb84aa6cd47e13d -size 83368 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-15-pseudo.New.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-15-pseudo.New.png deleted file mode 100644 index 5d845d1027..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-15-pseudo.New.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:586d337d138b6e48c05b748158bf764ae1ba57c70238937a6d0b330893b53eeb -size 87881 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollOptionView-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollOptionView-iPad-en-GB.1.png deleted file mode 100644 index ccdfed8b90..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollOptionView-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f2adb518ccd613e53f7d5618c108adaf22e813a77a9bd1043c97085a6f55063d -size 90813 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollOptionView-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollOptionView-iPad-pseudo.1.png deleted file mode 100644 index 2d9c26708c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollOptionView-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e0e6fd6b3ef402c173ab3dedefef32327255a9dd04abab1e8b15f3d8ef53ca32 -size 97544 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollOptionView-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollOptionView-iPhone-15-en-GB.1.png deleted file mode 100644 index e7d204a927..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollOptionView-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c2d3da86c311539d1f12542426fb2e8cdeaf440137a06ef82453a98f1e8f0ac2 -size 48935 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollOptionView-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollOptionView-iPhone-15-pseudo.1.png deleted file mode 100644 index 9d1e6a1136..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollOptionView-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a5d97beb7e44f6df2cbff25a10d45d4da38a949fb8ca9614e70e9afd6eed191f -size 57829 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Creator-disclosed-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Creator-disclosed-Bubble.png deleted file mode 100644 index 3cc67be069..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Creator-disclosed-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9f0456fdb365fb42bb47b3c1b2bee34593afa2eb40baf777b71768ea30120281 -size 120698 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Creator-no-votes-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Creator-no-votes-Bubble.png deleted file mode 100644 index 3383c7ac25..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Creator-no-votes-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5efddcf81e8839f3f8aa2f0d06a6efb592e4ceff3358c1faaafe334f0d351b14 -size 120413 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Disclosed-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Disclosed-Bubble.png deleted file mode 100644 index 05007e96da..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Disclosed-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2fc263347490f7af21e1f1643b9f67edd693dcf56acb6b40ab5ffc1e4eece6b5 -size 115126 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Ended-Disclosed-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Ended-Disclosed-Bubble.png deleted file mode 100644 index 6dd11e8057..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Ended-Disclosed-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ac24bad8a45e5a5221740f35c283854be08f06b15c72bd07c17d58eaf2e66373 -size 114987 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Ended-Undisclosed-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Ended-Undisclosed-Bubble.png deleted file mode 100644 index 6dd11e8057..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Ended-Undisclosed-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ac24bad8a45e5a5221740f35c283854be08f06b15c72bd07c17d58eaf2e66373 -size 114987 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Undisclosed-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Undisclosed-Bubble.png deleted file mode 100644 index a023a2b1dc..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Undisclosed-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ad388593723a7b9dfc6c6044b28173bd20791ca120921846ac977420ccbffbfc -size 111784 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Creator-disclosed-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Creator-disclosed-Bubble.png deleted file mode 100644 index ff3896fa5f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Creator-disclosed-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7486a5a9d7c45e74b5af86fbd8be4625b2c31fad5d43462f01e55d4ef438a4b1 -size 135017 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Creator-no-votes-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Creator-no-votes-Bubble.png deleted file mode 100644 index c1444f7904..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Creator-no-votes-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1e63e792811cc9b5e8efd3195b74ecf533e0370c4c2d57d4d9e156204a73b662 -size 134595 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Disclosed-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Disclosed-Bubble.png deleted file mode 100644 index b12d921226..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Disclosed-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8db10c517a6e759761743a3265484ba0342844003be50336fe7cdae911d6f34d -size 130334 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Ended-Disclosed-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Ended-Disclosed-Bubble.png deleted file mode 100644 index a69bc2314a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Ended-Disclosed-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e9ffeaeb00d0f8f52f2a9bfe52ee334392e52b0fa8f6abab1f16e2799ad081e7 -size 128653 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Ended-Undisclosed-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Ended-Undisclosed-Bubble.png deleted file mode 100644 index a69bc2314a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Ended-Undisclosed-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e9ffeaeb00d0f8f52f2a9bfe52ee334392e52b0fa8f6abab1f16e2799ad081e7 -size 128653 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Undisclosed-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Undisclosed-Bubble.png deleted file mode 100644 index 6564db7393..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Undisclosed-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ab884a3ce10a0fa37b87c28baf100950b19e7804a09917054e5e9b67bf2563f4 -size 117046 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-en-GB.Creator-disclosed-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-en-GB.Creator-disclosed-Bubble.png deleted file mode 100644 index d41104725f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-en-GB.Creator-disclosed-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a959d5915224374e5f8399c575fcf075a5afc1e90fc91450511bea97060b553c -size 73373 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-en-GB.Creator-no-votes-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-en-GB.Creator-no-votes-Bubble.png deleted file mode 100644 index 6e739beabd..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-en-GB.Creator-no-votes-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b2dbd1001ac0209241f7c2ce89d181101c1d000638b1ea1eaa459d4acd713174 -size 73137 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-en-GB.Disclosed-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-en-GB.Disclosed-Bubble.png deleted file mode 100644 index 4b09f83dd2..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-en-GB.Disclosed-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8dee67bd39829f1c84fc956a45bddc61315a233add65c6af379d107a340541ea -size 69019 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-en-GB.Ended-Disclosed-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-en-GB.Ended-Disclosed-Bubble.png deleted file mode 100644 index fb4a1b1323..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-en-GB.Ended-Disclosed-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b5665001aa153b313f0668cecb1985434e6e35f0a4889e1f238e929598d74bb4 -size 68201 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-en-GB.Ended-Undisclosed-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-en-GB.Ended-Undisclosed-Bubble.png deleted file mode 100644 index fb4a1b1323..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-en-GB.Ended-Undisclosed-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b5665001aa153b313f0668cecb1985434e6e35f0a4889e1f238e929598d74bb4 -size 68201 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-en-GB.Undisclosed-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-en-GB.Undisclosed-Bubble.png deleted file mode 100644 index 48c48fe905..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-en-GB.Undisclosed-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:59c7b8e194213a1a1f99e47299ed90098f3e448b0986b46910c796f810de2d4f -size 67181 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-pseudo.Creator-disclosed-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-pseudo.Creator-disclosed-Bubble.png deleted file mode 100644 index a067f90f7e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-pseudo.Creator-disclosed-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d571a2c9faebc12246b9da978f42becc9de7577de29ebdab5dc45f40b0da6a6a -size 86527 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-pseudo.Creator-no-votes-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-pseudo.Creator-no-votes-Bubble.png deleted file mode 100644 index 3e4003d817..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-pseudo.Creator-no-votes-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:94960bfeeaace295bff6e9332ca8153a5f9c6ff236f4673ee0a4672d25140e3b -size 85865 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-pseudo.Disclosed-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-pseudo.Disclosed-Bubble.png deleted file mode 100644 index 2a8d78f061..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-pseudo.Disclosed-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:85f2b02e7f09c6a46076ecc261aeb6e04fcb2df0d208cdf435a77c76db81f436 -size 81502 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-pseudo.Ended-Disclosed-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-pseudo.Ended-Disclosed-Bubble.png deleted file mode 100644 index 202c8b73ed..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-pseudo.Ended-Disclosed-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7dafea47e32228c50dfb51c7ae21866907ec26b55ddd824024277ee0f21ec166 -size 86746 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-pseudo.Ended-Undisclosed-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-pseudo.Ended-Undisclosed-Bubble.png deleted file mode 100644 index 202c8b73ed..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-pseudo.Ended-Undisclosed-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7dafea47e32228c50dfb51c7ae21866907ec26b55ddd824024277ee0f21ec166 -size 86746 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-pseudo.Undisclosed-Bubble.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-pseudo.Undisclosed-Bubble.png deleted file mode 100644 index 6378bb4f33..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-15-pseudo.Undisclosed-Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:966ce86f04fcb24f5ca8b02de2dfe37604682d1f928c5862a3ba80707eceb62e -size 73304 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Creator-disclosed.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Creator-disclosed.png deleted file mode 100644 index 4a1c217883..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Creator-disclosed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:147d0d5cc5262766db71ee0d3590906be7a8bafd64ef27ed396145fd61a9eea4 -size 109848 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Creator-no-votes.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Creator-no-votes.png deleted file mode 100644 index 883764624c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Creator-no-votes.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:adeba6908334188fb96e248764216758b28904414ce8d34c18970fb5a0e8d326 -size 109351 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Disclosed.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Disclosed.png deleted file mode 100644 index ac8bd6b126..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Disclosed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8c2ddf69fcccb6514208f9e5be2544ddefca71eaae89ba4c822c560cfd9e5bc1 -size 104303 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Ended-Disclosed.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Ended-Disclosed.png deleted file mode 100644 index c315a8c725..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Ended-Disclosed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2e729f041f6a8d78f4d0c7699c4fa01abbf2601478f08de976f84d56b5c5b692 -size 104751 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Ended-Undisclosed.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Ended-Undisclosed.png deleted file mode 100644 index c315a8c725..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Ended-Undisclosed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2e729f041f6a8d78f4d0c7699c4fa01abbf2601478f08de976f84d56b5c5b692 -size 104751 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Undisclosed.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Undisclosed.png deleted file mode 100644 index cacfca0658..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-en-GB.Undisclosed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8bd95932a60c08fc22c25ecdae447c64ef2e595bcd4f42d9db62a6618fcbcfa0 -size 101050 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Creator-disclosed.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Creator-disclosed.png deleted file mode 100644 index 020eb7b207..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Creator-disclosed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b34c915b6a049f923ccebbdea436cd87d6900ee7bc03792640f3aa50ad78245e -size 124241 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Creator-no-votes.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Creator-no-votes.png deleted file mode 100644 index d7458c0b29..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Creator-no-votes.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a56256b7ab72a469131d22a0966e592e4fa34a230c39c17be9eaa23efa13e6ff -size 123518 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Disclosed.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Disclosed.png deleted file mode 100644 index a561da1b20..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Disclosed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2a30b39a349080791a852750bbda5c63a9da41f6a816f57e490ba94f5da8e91f -size 118698 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Ended-Disclosed.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Ended-Disclosed.png deleted file mode 100644 index 2066d23a3e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Ended-Disclosed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9ecc0d5179328a2852167f9cde7445faf6e946ae2f9d916ebaa581001c8682f2 -size 118639 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Ended-Undisclosed.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Ended-Undisclosed.png deleted file mode 100644 index 2066d23a3e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Ended-Undisclosed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9ecc0d5179328a2852167f9cde7445faf6e946ae2f9d916ebaa581001c8682f2 -size 118639 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Undisclosed.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Undisclosed.png deleted file mode 100644 index cf688b447a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPad-pseudo.Undisclosed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c590e9c56bd23ceb4a18ae090bfd7570acafe5c7b111d877f90542773c827183 -size 105607 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-en-GB.Creator-disclosed.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-en-GB.Creator-disclosed.png deleted file mode 100644 index 614f7e0e67..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-en-GB.Creator-disclosed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cd182137b3ffe70f92d12ac2d8fc94667db804470695421068d95491046963ab -size 63790 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-en-GB.Creator-no-votes.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-en-GB.Creator-no-votes.png deleted file mode 100644 index d2a3bf6de8..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-en-GB.Creator-no-votes.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:90d2c2050f4abbb1437e321f79f1a192030b6a122a49dc8b562f282eae66a259 -size 63326 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-en-GB.Disclosed.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-en-GB.Disclosed.png deleted file mode 100644 index c7890d61db..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-en-GB.Disclosed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a617920e7ff77d21a4b89496250231eb5cccc1a44117d80eb6adca8e8d1f1822 -size 59385 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-en-GB.Ended-Disclosed.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-en-GB.Ended-Disclosed.png deleted file mode 100644 index 5b14806a44..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-en-GB.Ended-Disclosed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:15d87c95885d1cad4e5d17bf8fedd24b4c3a47b86be56905273424ee15833107 -size 59835 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-en-GB.Ended-Undisclosed.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-en-GB.Ended-Undisclosed.png deleted file mode 100644 index 5b14806a44..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-en-GB.Ended-Undisclosed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:15d87c95885d1cad4e5d17bf8fedd24b4c3a47b86be56905273424ee15833107 -size 59835 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-en-GB.Undisclosed.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-en-GB.Undisclosed.png deleted file mode 100644 index 75f8f8e948..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-en-GB.Undisclosed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:27bbf5c75a05e2582e5f1c0c808b1406a1d0c6862f796c578b7f967d11a25259 -size 56433 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-pseudo.Creator-disclosed.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-pseudo.Creator-disclosed.png deleted file mode 100644 index dde081133d..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-pseudo.Creator-disclosed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4fae0ca419603eabef18fed74e1860346a39b3cb3867655dd4f6f550366915ec -size 80562 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-pseudo.Creator-no-votes.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-pseudo.Creator-no-votes.png deleted file mode 100644 index 4ec0525822..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-pseudo.Creator-no-votes.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:713f1f9cd608c032935dc4b4aa78823dfd72c45c7eb82d25e1e6940b07927906 -size 79802 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-pseudo.Disclosed.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-pseudo.Disclosed.png deleted file mode 100644 index 644e5c809e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-pseudo.Disclosed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ee0483762b2a5854ffc13f159d543d12eb4301efba6af9a952085a146bea81d4 -size 75724 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-pseudo.Ended-Disclosed.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-pseudo.Ended-Disclosed.png deleted file mode 100644 index f3b1f5147d..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-pseudo.Ended-Disclosed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e46f03b1fbb21f75f1751245289e4a186f17a228bb303d9916c3d7c423cb8643 -size 75639 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-pseudo.Ended-Undisclosed.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-pseudo.Ended-Undisclosed.png deleted file mode 100644 index f3b1f5147d..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-pseudo.Ended-Undisclosed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e46f03b1fbb21f75f1751245289e4a186f17a228bb303d9916c3d7c423cb8643 -size 75639 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-pseudo.Undisclosed.png b/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-pseudo.Undisclosed.png deleted file mode 100644 index c52843956f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pollView-iPhone-15-pseudo.Undisclosed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:be106e3855942428c0711922eec21e463429e821c41db89715a6accecbe61991 -size 61169 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Connection-not-secure.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Connection-not-secure.png deleted file mode 100644 index abc24591c9..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Connection-not-secure.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cb32ea687c401edd37c930a52cb39f10706492febc81eadefcd002a912fc715c -size 160275 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Device-code.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Device-code.png deleted file mode 100644 index c86d6354d1..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Device-code.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:63438818d5a2683993702c2975991f38659e734e32d32f26bc5ffc9f8517a0f5 -size 117622 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Initial.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Initial.png deleted file mode 100644 index 794bce8534..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Initial.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:340aa72b75fe1cc4b14181c679e7b97d979134c46f483f36de263644c947ce14 -size 135676 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Verification-code.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Verification-code.png deleted file mode 100644 index db132f12f2..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Verification-code.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e62e44b323182da43dde53dd5cdd32c898f687f08cbe92891c9ff68d70d69ef0 -size 122847 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Connection-not-secure.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Connection-not-secure.png deleted file mode 100644 index 54f3da189a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Connection-not-secure.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:34c6de864514d29478e35db01699461dab978e1d2b73134c1b2b51a4e81d0df2 -size 212015 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Device-code.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Device-code.png deleted file mode 100644 index 7cbe3240a4..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Device-code.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cd2c7d9aed8cc15486abbfa3611efe2669616cf194cb0e46151b1af14af1874c -size 139685 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Initial.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Initial.png deleted file mode 100644 index 096ef04be5..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Initial.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b3d8ef1a1f86eb57817a86ee99e04df478fc1d8ea4d4e6daac5f70c63e683461 -size 163653 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Verification-code.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Verification-code.png deleted file mode 100644 index 081820b15a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Verification-code.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bd42762b7bc264ee8a6cd81bfa4ecd312b41302c220342faf49fb2cc69024d3d -size 139396 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Connection-not-secure.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Connection-not-secure.png deleted file mode 100644 index c13174157a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Connection-not-secure.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9955b663d6e3de10531bd6d6401d703f5b72f5e5dd17a1dbc13ff0817caeafdb -size 108054 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Initial.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Initial.png deleted file mode 100644 index 979caaeb6e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Initial.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:945acff8dfacd26ec6914ec91fcafcf3721682f8469593fbc6b5b5fec87c2eca -size 83469 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Verification-code.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Verification-code.png deleted file mode 100644 index 4d87674092..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Verification-code.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5d5d2d76199dd4364b03ebca6a529672b576da39e1f52a88e6484fe45ac7fc47 -size 70532 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Connection-not-secure.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Connection-not-secure.png deleted file mode 100644 index 2ce0157341..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Connection-not-secure.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:56e0e126740e8659379fac67d11b85a81fbbc45c13d93a2710cd7807ce3645ad -size 163555 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Initial.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Initial.png deleted file mode 100644 index 2b7e46bcd4..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Initial.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:84e15f7feff408b6c8ba837c6c1bc4466690d1f8b591fcf46b09c4739232f5bc -size 116680 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Verification-code.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Verification-code.png deleted file mode 100644 index 6a03bdc4a4..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Verification-code.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f3483324558717d1fcae1087d6d1a580d5b8debfbed57eb764631f98c5f6d678 -size 93122 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPad-en-GB.1.png deleted file mode 100644 index e8110a70f9..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a58785700083ec36c8ac285dd1958ad4b963a2657108dfa7395a47127bac614a -size 157694 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPad-pseudo.1.png deleted file mode 100644 index d02a52b4f9..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:584319d6bc6d1843a54539b30badc8e2d807545b36fdda1e1367957bb0063c84 -size 158602 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPhone-15-en-GB.1.png deleted file mode 100644 index d18efbcfde..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0a48ef281f96493788fd397f00fc89395d8042dc0c01692547e0dde26e84b928 -size 65239 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPhone-15-pseudo.1.png deleted file mode 100644 index f4e84979b5..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_reactionsSummaryView-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1d988c57a73be29d0f47c370251161403c62161b3bc82fd94e2ff0b87fd3bf59 -size 65916 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_reportContentScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_reportContentScreen-iPad-en-GB.1.png deleted file mode 100644 index b64a900aa8..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_reportContentScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:361116282842dc256df746a85d54a1db57e0355b8c3e9ff64f95b4c6b59d0989 -size 121796 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_reportContentScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_reportContentScreen-iPad-pseudo.1.png deleted file mode 100644 index f113f496c1..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_reportContentScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3cd81db475fc8f8f3488268927ec076f18f3aa80beff7baf6707781ee11205fc -size 142438 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-15-en-GB.1.png deleted file mode 100644 index 8822313811..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:96f3905550e609576d0453336ac3cf863be0d94dacfee669b95403232860773a -size 76803 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-15-pseudo.1.png deleted file mode 100644 index c367cb597c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dfe0eff65b57567cf818e5433a2f9031bbe00b6d26fe7fc11e6598f12381d024 -size 107478 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-en-GB.Member-moderation.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-en-GB.Member-moderation.png deleted file mode 100644 index 154890e758..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-en-GB.Member-moderation.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:12c7f7d8c8137eb42918c23b0415d90870dbdb17dd2c236e747e84b9edb0c8ea -size 134383 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-en-GB.Messages-and-Content.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-en-GB.Messages-and-Content.png deleted file mode 100644 index eb678f61a1..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-en-GB.Messages-and-Content.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dc48ca8d83e1f3f84df75535204fec809ca97e8c24a99f27dc38e37e38571dd9 -size 120905 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-en-GB.Room-details.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-en-GB.Room-details.png deleted file mode 100644 index f3fe18e1a2..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-en-GB.Room-details.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:61fb9fb23734ee3beca6ac82629e0b83eb3695a73e5890f947593d8a72fb440f -size 140079 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-pseudo.Member-moderation.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-pseudo.Member-moderation.png deleted file mode 100644 index fbe09314f1..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-pseudo.Member-moderation.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6964fd3f7c6eed4112a244aacaf646c6135b6d05b49482fb1308b3537a571fed -size 147190 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-pseudo.Messages-and-Content.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-pseudo.Messages-and-Content.png deleted file mode 100644 index f361fa963f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-pseudo.Messages-and-Content.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:14875777275fd26578d420195d47991660c622c75befb7085411de93e638378f -size 130088 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-pseudo.Room-details.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-pseudo.Room-details.png deleted file mode 100644 index 3c1dbda179..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPad-pseudo.Room-details.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:59adec798a11493e482cdd815247282101f68566b4809011d61c42a0005dea89 -size 153777 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-15-en-GB.Member-moderation.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-15-en-GB.Member-moderation.png deleted file mode 100644 index 9e25bf2148..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-15-en-GB.Member-moderation.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a9b964d5c8f99c85d957e447c85eda83f3a234f6df3eb4ce4a05024c538f9dcf -size 81009 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-15-en-GB.Messages-and-Content.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-15-en-GB.Messages-and-Content.png deleted file mode 100644 index bdf242853d..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-15-en-GB.Messages-and-Content.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f96cad6d912e6d286fbbb314fc8c5e66cacf235153a9b591607fe1539efb5e72 -size 69530 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-15-en-GB.Room-details.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-15-en-GB.Room-details.png deleted file mode 100644 index d82239a3a2..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-15-en-GB.Room-details.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:748aa058f232e6658652c82ce9d4d0d3b9c8486e7353527157e935465018512a -size 85721 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-15-pseudo.Member-moderation.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-15-pseudo.Member-moderation.png deleted file mode 100644 index 8e92832639..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-15-pseudo.Member-moderation.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:846916da7450684c392134de8719f2cd49728e1afcfb04761d3c4adb266ef8bf -size 101855 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-15-pseudo.Messages-and-Content.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-15-pseudo.Messages-and-Content.png deleted file mode 100644 index c5ab5f6279..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-15-pseudo.Messages-and-Content.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a198230caf882659d6e48c794c5c53dc64584515747bdf84c853233e6a632fee -size 83924 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-15-pseudo.Room-details.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-15-pseudo.Room-details.png deleted file mode 100644 index 0d26f0cbed..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangePermissionsScreen-iPhone-15-pseudo.Room-details.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:be6fa28709a6955fab957b98229fb85a051acb9d23a44f35356c8b678b9e19c1 -size 108600 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-en-GB.Administrators.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-en-GB.Administrators.png deleted file mode 100644 index ace02b6fad..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-en-GB.Administrators.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dd9d4db2a3a1728e21e74bd60b2e2e4a1a81782f7a40e22f282e26398fd10d5d -size 190128 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-en-GB.Moderators.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-en-GB.Moderators.png deleted file mode 100644 index 2e282fa976..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-en-GB.Moderators.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9a8ec1b8c5bedccf3f3a75d6e8435e9a1c2bc15877d84861febf794aa13bba21 -size 175407 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-pseudo.Administrators.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-pseudo.Administrators.png deleted file mode 100644 index 4411dcc569..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-pseudo.Administrators.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5491597dd7f2c350d2df545a52a534d5b4692398e6581a00429507863c90a111 -size 196175 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-pseudo.Moderators.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-pseudo.Moderators.png deleted file mode 100644 index abe5f82b91..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-pseudo.Moderators.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:aecc24f0596b9fcbe6fd481c74c5928d949db4885de213a65eac568f4d260806 -size 185859 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-15-en-GB.Administrators.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-15-en-GB.Administrators.png deleted file mode 100644 index 2943eb65b7..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-15-en-GB.Administrators.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3d55578df9cc28f7b84d5d012b05b27f27d2717ad066f9799864ae0795b3fe3e -size 141251 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-15-en-GB.Moderators.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-15-en-GB.Moderators.png deleted file mode 100644 index 0bc755fe3b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-15-en-GB.Moderators.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d6d70adcae5c586a4cfd8ea9adf0fac65ac58b0ca596529c2179483137202d5e -size 129325 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-15-pseudo.Administrators.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-15-pseudo.Administrators.png deleted file mode 100644 index 788e86492f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-15-pseudo.Administrators.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e67b139e5b50b5666c1030d69630b70344b21fbbe002ac2da187383cbe276f70 -size 146829 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-15-pseudo.Moderators.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-15-pseudo.Moderators.png deleted file mode 100644 index ce28f779d5..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-15-pseudo.Moderators.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9894db28920051b906e21630a39794f35d8808e72c0338cef4473995dd0a01c6 -size 138470 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPad-en-GB.1.png deleted file mode 100644 index 8ed82422ca..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7dda561c53ff66c7776d52bfeba1348ee9ccbddb22874f6834f49fb14fd2fdde -size 46068 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPad-pseudo.1.png deleted file mode 100644 index 8ed82422ca..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7dda561c53ff66c7776d52bfeba1348ee9ccbddb22874f6834f49fb14fd2fdde -size 46068 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPhone-15-en-GB.1.png deleted file mode 100644 index 7fbe1c36cf..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f8d8cfd9a1a642bc40c31bcad4340ea375871e93f23429c8ef381864d63a2ec9 -size 36343 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPhone-15-pseudo.1.png deleted file mode 100644 index 7fbe1c36cf..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f8d8cfd9a1a642bc40c31bcad4340ea375871e93f23429c8ef381864d63a2ec9 -size 36343 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-en-GB.Editable.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-en-GB.Editable.png deleted file mode 100644 index ad99e17d57..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-en-GB.Editable.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7f9c885a46b6f87ddd30839b9b63bcac9fc71c7beedb0435820b78ff21644d4f -size 106377 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-en-GB.Read-only.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-en-GB.Read-only.png deleted file mode 100644 index 4170c4e8bc..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-en-GB.Read-only.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cbbc3442d1a9e2ff6ffd6fd7b3d2fd3f0e337fff4daf57d94cf1f2c8d18a9b9c -size 95696 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-pseudo.Editable.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-pseudo.Editable.png deleted file mode 100644 index 74cf4ec3b4..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-pseudo.Editable.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6aa010c6deedb6e09653ec182780119823057868410e401a57aa9337e7be2f38 -size 114757 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-pseudo.Read-only.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-pseudo.Read-only.png deleted file mode 100644 index ffbf02d23c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-pseudo.Read-only.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b64f15d5515986b70f16ac4fce3d3af098ba59bd1d1cbf6e36142e357dc6e02c -size 101172 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-15-en-GB.Editable.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-15-en-GB.Editable.png deleted file mode 100644 index d6bb78343c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-15-en-GB.Editable.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:14a2586353494254e5603c852a311aa4b49526e34988e0563b0e878b1829975a -size 57815 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-15-en-GB.Read-only.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-15-en-GB.Read-only.png deleted file mode 100644 index 7f251b44d9..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-15-en-GB.Read-only.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f5497ae07726c6cd213dda3a7784e4addf2354c0a8e00694d44ef62a50d12cc9 -size 49212 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-15-pseudo.Editable.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-15-pseudo.Editable.png deleted file mode 100644 index 779c171aff..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-15-pseudo.Editable.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f2b888f5922264636b23da8bbb3bf3f4319eaed22fa3dbd7d3f3a2a808983444 -size 67382 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-15-pseudo.Read-only.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-15-pseudo.Read-only.png deleted file mode 100644 index 728c0ec3de..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-15-pseudo.Read-only.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f918ec184265dcedcc2bd4422ecd677dae2dec0b2315adda53dd4f36b7c6a5b2 -size 53887 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPad-en-GB.1.png deleted file mode 100644 index 709e9002ce..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:876bf67a8d40cd6723e138d0a1f758970ce5a99b1f3eb86a7f5837b4110e8b54 -size 93310 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPad-pseudo.1.png deleted file mode 100644 index 9964d1873c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:19c316b457d6510ea795cee9dba46f337a864502a82fe009e01ca0590ef7d2a3 -size 95930 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPhone-15-en-GB.1.png deleted file mode 100644 index ee60507f63..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7ccf6b3e3ab0026c09113c61da1e45c5b647a9a87985ad16794b4d88a9f6ad52 -size 49965 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPhone-15-pseudo.1.png deleted file mode 100644 index 4b3c676209..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomDirectorySearchScreen-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e917c0c4d169528bbf02163c1b4154e7ba5277733500db8741afdfe4f7f256c0 -size 52473 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-en-GB.1.png deleted file mode 100644 index 70ce58113c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:35ee0cae82949fb75bb35a363fb4d42a5d17b6078470dfa551d23032728d1c8c -size 16294 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-en-GB.2.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-en-GB.2.png deleted file mode 100644 index 7b3353fea8..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-en-GB.2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:22d5ca697d1f6ee3cacf815d5a4b1136ca1b16d428e665199aba42e13a45301b -size 11425 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-pseudo.1.png deleted file mode 100644 index 70ce58113c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:35ee0cae82949fb75bb35a363fb4d42a5d17b6078470dfa551d23032728d1c8c -size 16294 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-pseudo.2.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-pseudo.2.png deleted file mode 100644 index 7b3353fea8..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-pseudo.2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:22d5ca697d1f6ee3cacf815d5a4b1136ca1b16d428e665199aba42e13a45301b -size 11425 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-15-en-GB.1.png deleted file mode 100644 index d3dd446940..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4e3b382b63d456532e4ad16adc59f1780d36c37f7269b09394b737bba7833dd3 -size 12453 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-15-en-GB.2.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-15-en-GB.2.png deleted file mode 100644 index 03fadd479e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-15-en-GB.2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fdd16440888db9053c4c601295de4725574a224d0fdb4a87ab361cb30b20e3df -size 7867 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-15-pseudo.1.png deleted file mode 100644 index d3dd446940..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4e3b382b63d456532e4ad16adc59f1780d36c37f7269b09394b737bba7833dd3 -size 12453 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-15-pseudo.2.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-15-pseudo.2.png deleted file mode 100644 index 03fadd479e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-15-pseudo.2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fdd16440888db9053c4c601295de4725574a224d0fdb4a87ab361cb30b20e3df -size 7867 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView-iPad-en-GB.2.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView-iPad-en-GB.2.png deleted file mode 100644 index 0e371ce972..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView-iPad-en-GB.2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:af47953b4fea7a877a15e0b8d8049fbbc24450c9af180c2fa8cec532af59daa2 -size 79576 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView-iPad-pseudo.2.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView-iPad-pseudo.2.png deleted file mode 100644 index b761039a8e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView-iPad-pseudo.2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a66004a8c96806af5d787b51d02b86eae3b1fb4f71143177ffd7efc0f1bea62e -size 80953 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView-iPhone-15-en-GB.2.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView-iPhone-15-en-GB.2.png deleted file mode 100644 index 2fa200a506..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView-iPhone-15-en-GB.2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3278a6c981805648a352a12c5a41883243a77bc927243a9aa6607fc7f753f2e2 -size 38446 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView-iPhone-15-pseudo.2.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView-iPhone-15-pseudo.2.png deleted file mode 100644 index 04c84b4a27..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView-iPhone-15-pseudo.2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:84c98c8f288dcb26ab8aa41a49a02dba71ccbd3cafc513cd050df75992ac4d50 -size 34965 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPad-en-GB.1.png deleted file mode 100644 index a68aca3796..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:afb705ab38ef8224088a4c7f4f803851f9e50f077173abdd5d084639ab590113 -size 157469 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPad-pseudo.1.png deleted file mode 100644 index 2d5c792379..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8e3e4c4db47293f42a6f9efe758e096634eafecd6f99b5a923b7ebf59e4cea85 -size 161191 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPhone-15-en-GB.1.png deleted file mode 100644 index ce4b684458..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:97acce766c898e2eef0fdedf249b9a51d156fb0514b578022ce4a158e80b8857 -size 103431 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPhone-15-pseudo.1.png deleted file mode 100644 index 812bb47138..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b820715b4dff07b21b3dfba50ec82d15c12a80091082370a518b7b0226fa7f82 -size 107876 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Banned.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Banned.png deleted file mode 100644 index c1e5e6bd30..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Banned.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:61f2e22325fd063c8be96110f2c5e1476dcc7b498c5cca33bbf8b6caaec84b6a -size 116785 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Empty-Banned.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Empty-Banned.png deleted file mode 100644 index f6e6a481f2..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Empty-Banned.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e0511f38ff397cef55d919066eb132ae9dc7f6a104e4b5edf49582e418e95b72 -size 92153 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Members.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Members.png deleted file mode 100644 index bdbd5c8bef..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Members.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4c7968014a36102ea9d958056fa423d0375217ab8792ab1e954d10fe96748555 -size 132934 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Invites.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Invites.png deleted file mode 100644 index 78959d6878..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Invites.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:db8f98be7aa49cbb312d7067d1330a9091971359c09aad1cea43a718b225a55b -size 136144 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Member.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Member.png deleted file mode 100644 index 3582cd231a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Member.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c215d1f286502712ca572b828cb2667b961b2e1b4090c419d691d44b73dea944 -size 125563 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Banned.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Banned.png deleted file mode 100644 index f90ff4143f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Banned.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4a13dff5c87fa38b7f8270d60d78b9282c9b94603c03e436c5c4c3d9911f2e0f -size 121491 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Empty-Banned.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Empty-Banned.png deleted file mode 100644 index ff416b0bf1..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Empty-Banned.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:97a1c99218c8c2590bf3afd8b45f025abf926e6a5d9bec98edff4f4d308ddd7d -size 100546 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Members.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Members.png deleted file mode 100644 index aa0500d906..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Members.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:df8a74b6caf4b488c3fcf8d00f50e376beadd149d7ccb5049f9392618c6bd89e -size 141776 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Invites.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Invites.png deleted file mode 100644 index 8276da30b4..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Invites.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c78027df4dc3465530fc1e187b14568f72e8102956ccdd526acacbbfad349ba7 -size 144234 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Member.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Member.png deleted file mode 100644 index cc6c0464a2..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Member.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:14f9633a30ec6abc37c81adae999169e26d6920da44aba4eae916dfe85578d31 -size 133393 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-en-GB.Admin-Banned.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-en-GB.Admin-Banned.png deleted file mode 100644 index 68e8240217..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-en-GB.Admin-Banned.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fd6206b16d5f5a1f458c9feeb43857569f15ee02c0bd7815cedd5324b947a7a9 -size 68428 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-en-GB.Admin-Empty-Banned.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-en-GB.Admin-Empty-Banned.png deleted file mode 100644 index 1b45f1736b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-en-GB.Admin-Empty-Banned.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:160285e178bc57684b576e8e7e7383a2ece0cec69616367d0249879ebde35c49 -size 48822 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-en-GB.Admin-Members.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-en-GB.Admin-Members.png deleted file mode 100644 index 26dac9dd78..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-en-GB.Admin-Members.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8c569c30f1ed83185fa663082de524f9363819ee77113e30bc8271fd8c371c7b -size 83815 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-en-GB.Invites.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-en-GB.Invites.png deleted file mode 100644 index 180c12af99..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-en-GB.Invites.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5d894cd7d8a74e90dc5afc2e0b42854fae55e3aac0fb50d1c54a969b1bbb613c -size 86271 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-en-GB.Member.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-en-GB.Member.png deleted file mode 100644 index 5922559861..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-en-GB.Member.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:898ae196ef98917c400b3953273434ad0958d18abc81b573c51927d289ccd657 -size 37094 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-pseudo.Admin-Banned.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-pseudo.Admin-Banned.png deleted file mode 100644 index a85ca072a2..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-pseudo.Admin-Banned.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bdd029fbc3843b1b402f14a4f262bf615d284a2f2b86961df5016911bf2ab3f6 -size 73632 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-pseudo.Admin-Empty-Banned.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-pseudo.Admin-Empty-Banned.png deleted file mode 100644 index fa4a5d8c91..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-pseudo.Admin-Empty-Banned.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fbb9dbab6d41bd10dc63e573fb576edc5079793c679f434616196cc3bd2eac04 -size 59338 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-pseudo.Admin-Members.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-pseudo.Admin-Members.png deleted file mode 100644 index 0a8f2b44c2..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-pseudo.Admin-Members.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d9056f771e440c2b8336e8cb97e1d262c2c9455f55cd88dced7e8f403c3edffb -size 93537 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-pseudo.Invites.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-pseudo.Invites.png deleted file mode 100644 index d1d0c2e0c4..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-pseudo.Invites.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:21bd2bbbd179591e2de14319c15eab8650f28450b07f55bbc7a91f56398ab28d -size 96454 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-pseudo.Member.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-pseudo.Member.png deleted file mode 100644 index 2d0a1bea9b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-15-pseudo.Member.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:752d85574e015fd1ee805cae690c0361940bacb39dbb953aa0bede0b069619dd -size 40696 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-en-GB.No-polls.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-en-GB.No-polls.png deleted file mode 100644 index aa73e71f39..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-en-GB.No-polls.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:025e5b02975715bc4a25cce368aad568c754220cf83f5b404cbfb16bec01b221 -size 97418 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-en-GB.polls.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-en-GB.polls.png deleted file mode 100644 index f3cb463a47..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-en-GB.polls.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4b4c342c3a0fc49e65dbaf9be263a40199ccca5150460a2f524af747c6e41da0 -size 187273 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-pseudo.No-polls.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-pseudo.No-polls.png deleted file mode 100644 index eed38c4f6b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-pseudo.No-polls.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ec6b9041262caa28524d050314bc1bf80f7c3ce391876f84736e4a2505db586f -size 105475 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-pseudo.polls.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-pseudo.polls.png deleted file mode 100644 index 52559387fb..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPad-pseudo.polls.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b78cb6f03f10c6ccefee7af9919aaa85a0397c060d44c33fe4d823aa9d23d638 -size 216097 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-15-en-GB.No-polls.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-15-en-GB.No-polls.png deleted file mode 100644 index 17f8d200ca..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-15-en-GB.No-polls.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:22bc2b4753cfa9ba16c0689df834c841066be7840f3b65e2ffa9ba083156bd07 -size 50255 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-15-en-GB.polls.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-15-en-GB.polls.png deleted file mode 100644 index 22cbc98c16..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-15-en-GB.polls.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f236e90053c0478fd4e183418f59f16bfe3e0d2073983a3c7c54f6bfc0fa7854 -size 119620 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-15-pseudo.No-polls.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-15-pseudo.No-polls.png deleted file mode 100644 index e35aad775b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-15-pseudo.No-polls.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1d2ef5cb8d85a8f028b415947e1e9711b3406fa21491c37b6bf7a15453d021ed -size 58505 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-15-pseudo.polls.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-15-pseudo.polls.png deleted file mode 100644 index 1adc55165d..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomPollsHistoryScreen-iPhone-15-pseudo.polls.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7b0311515975364995f72fd8db6768e0d31877f674edea1b77d88998ace1e276 -size 145965 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPad-en-GB.1.png deleted file mode 100644 index 652fd8dd24..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ea436449d7d1ea50814d1a67a7909aa1731267d000d5b1888a130406eb21c3fd -size 134172 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPad-pseudo.1.png deleted file mode 100644 index 3e1e34953f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dd4df9dff9fa925159360e2cf513346b8a28e7665bbe635da98c4f750b07d778 -size 148186 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPhone-15-en-GB.1.png deleted file mode 100644 index 566d8447c0..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:896d0c191c7e6dde6a2327c45b25af0c73247c1e14c3ff8f2c81b717f94d7b54 -size 83507 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPhone-15-pseudo.1.png deleted file mode 100644 index 11c00a525c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomRolesAndPermissionsScreen-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:09d3bda17bab224b6787f5966876c8c91d9d0d366c812f9637a99f467c8287c9 -size 100804 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomScreen-iPad-en-GB.1.png deleted file mode 100644 index beae942c9b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6067114ea694604ada52f8661d19c13093c9ca57fd0bd9dd76a61c22823287fc -size 295821 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomScreen-iPad-pseudo.1.png deleted file mode 100644 index 6a6cc62275..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:28f4aaac85bf4cec7d6ed18b3c7048dc4399c21c18b6d2ad4e3a16c0c1b27517 -size 297798 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomScreen-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomScreen-iPhone-15-en-GB.1.png deleted file mode 100644 index 58a32cb823..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomScreen-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:71180fc6e87efaa6811757379240288bab23f51f609869169acbc26a39ba0214 -size 180340 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomScreen-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomScreen-iPhone-15-pseudo.1.png deleted file mode 100644 index 5c0375c809..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomScreen-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9cd928134ee5d2aec167aef061ab03f764dac009d274227e43342fc8369e23f4 -size 178335 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sFNumberedListView-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_sFNumberedListView-iPad-en-GB.1.png deleted file mode 100644 index e79fc84804..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sFNumberedListView-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0239ab7a902f201b9d9f44d2062260e2021078e99e5feda2c86f078f6328a98b -size 67015 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sFNumberedListView-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_sFNumberedListView-iPad-pseudo.1.png deleted file mode 100644 index e79fc84804..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sFNumberedListView-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0239ab7a902f201b9d9f44d2062260e2021078e99e5feda2c86f078f6328a98b -size 67015 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sFNumberedListView-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_sFNumberedListView-iPhone-15-en-GB.1.png deleted file mode 100644 index 48b5b96cf6..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sFNumberedListView-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a6caa8a5473201670cfc65ca85f4ae1623e95e2667cfa32e9d7c7d3fbf15e921 -size 43654 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sFNumberedListView-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_sFNumberedListView-iPhone-15-pseudo.1.png deleted file mode 100644 index 48b5b96cf6..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sFNumberedListView-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a6caa8a5473201670cfc65ca85f4ae1623e95e2667cfa32e9d7c7d3fbf15e921 -size 43654 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupKeyBackupScreen-iPad-en-GB.Set-up.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupKeyBackupScreen-iPad-en-GB.Set-up.png deleted file mode 100644 index 94ab686f50..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupKeyBackupScreen-iPad-en-GB.Set-up.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:38e72f6c3f07b5f51a8ff85aaf16788cdf708ddf347824cf524950efdc6b9a52 -size 127859 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupKeyBackupScreen-iPad-pseudo.Set-up.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupKeyBackupScreen-iPad-pseudo.Set-up.png deleted file mode 100644 index df1c63f43b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupKeyBackupScreen-iPad-pseudo.Set-up.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:58d3d7680a6b2433c56868a1aaac12a198c67a6b98770f41f10b2fd8d6329afa -size 173765 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupLogoutConfirmationScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupLogoutConfirmationScreen-iPad-en-GB.1.png deleted file mode 100644 index 88affedd8f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupLogoutConfirmationScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a79a657d65246962e1e4798516a798d92564b81a45e2638405f4ddf1223464cc -size 108749 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupLogoutConfirmationScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupLogoutConfirmationScreen-iPad-pseudo.1.png deleted file mode 100644 index cb66db81db..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupLogoutConfirmationScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e785a0cc5e7d5300dc4ed3df23e430ce4bf72c6918d53c518913fdab6d8dae15 -size 130899 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Incomplete.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Incomplete.png deleted file mode 100644 index b0a7be820c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Incomplete.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9a245514a9a6e52f3c1106aad8bbca74de09f70fa22188c613d7c3d6feec70cc -size 111853 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Not-set-up.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Not-set-up.png deleted file mode 100644 index d55065724b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Not-set-up.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4638887e278dfe21eee64c24a7b07c5ab311ef8a4e689c802bac46954e4eb62f -size 123715 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Set-up.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Set-up.png deleted file mode 100644 index fc2718f4a1..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Set-up.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2603fed41dde708662e9ca8fc1f29303474af8f9a95e52e4c5897a7d4d01e857 -size 123894 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Unknown.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Unknown.png deleted file mode 100644 index 1c0e7ac21a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Unknown.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a4d9ef54544912910ed4a447c708b304c511f80263167c5dc3ad68b8076c51c2 -size 78683 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Incomplete.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Incomplete.png deleted file mode 100644 index 57aa5642f8..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Incomplete.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:88bad58775f77da5bc1a942ae31502c82725a45222b2776b9ecd3b48f69285ce -size 127822 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Not-set-up.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Not-set-up.png deleted file mode 100644 index 2b6c888ee0..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Not-set-up.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bdd8fb19399e506b534e7353376c2d155db360232ef615384d5f3f103fd16354 -size 151728 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Set-up.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Set-up.png deleted file mode 100644 index cf4e64851e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Set-up.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cb97c3e58e7bde1a65cf323af49408457f4f2c79a5ff6fddb7e73ea874a4eb4b -size 149702 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Unknown.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Unknown.png deleted file mode 100644 index bff2da1b49..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Unknown.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9c34ec6df77bdba0b2bfebeb44408b6a0d8e19ae158d6f6471139b426969eb51 -size 81272 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Both-setup.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Both-setup.png deleted file mode 100644 index 7c0cea1cb2..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Both-setup.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f95ea0a79cc0a1d66e29c5a378a67dfa6b86468bcb18b2f369f1f2d6360a524a -size 104770 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Key-backup-disabled.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Key-backup-disabled.png deleted file mode 100644 index 32f7c244e8..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Key-backup-disabled.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:60269d05a58a024204147702ca80981ec8404288d143998d4984f261bd4ad919 -size 97959 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Only-key-backup-setup.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Only-key-backup-setup.png deleted file mode 100644 index c42390009e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Only-key-backup-setup.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fa4e633a8d0c43b5c8e5394737edf435d5b47787c59a4c70ccbee8d8c048db23 -size 114976 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Recovery-incomplete.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Recovery-incomplete.png deleted file mode 100644 index 215f98f0cd..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-en-GB.Recovery-incomplete.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4cce85400044b5a55dbebaec985a904d7651fdfef61f9400657001ae4f5791e4 -size 91260 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Both-setup.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Both-setup.png deleted file mode 100644 index 796e61a9ee..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Both-setup.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0e8323c849898d4d37b82d4f05fd9cc7a1e76192d66b99f964d0b2e179dafc64 -size 114742 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Key-backup-disabled.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Key-backup-disabled.png deleted file mode 100644 index 49b8dd3f21..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Key-backup-disabled.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d0361540f8f07de5c5b84720b83374c9062bebec15e2cf5098ad803d952c0abb -size 104889 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Only-key-backup-setup.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Only-key-backup-setup.png deleted file mode 100644 index 1d61722edf..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Only-key-backup-setup.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:449c26f8ae7840df3146a19e628bcea6dd07a8acda0488c850b6844d6a53354b -size 135889 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Recovery-incomplete.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Recovery-incomplete.png deleted file mode 100644 index 9d585811b7..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPad-pseudo.Recovery-incomplete.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a3d39b5707492fadee29f04de3af877b381d08047103ddc60ebdd4c8de13b7ae -size 97842 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-en-GB.Both-setup.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-en-GB.Both-setup.png deleted file mode 100644 index 97a2a0b2f6..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-en-GB.Both-setup.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6cbe4c718c554155e8d2a9dc59c6a2f7575ccf8e9e303238849e2036f527cf9d -size 56909 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-en-GB.Key-backup-disabled.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-en-GB.Key-backup-disabled.png deleted file mode 100644 index 77f936db52..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-en-GB.Key-backup-disabled.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:137158e2c13f6f38862b38ec673a7e05f02b0f70254fa5cc08d81718c36d1206 -size 50276 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-en-GB.Only-key-backup-setup.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-en-GB.Only-key-backup-setup.png deleted file mode 100644 index 22dfd3e4da..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-en-GB.Only-key-backup-setup.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:60519f43ecdcf0f289ca5338ea06cd83274b3a32a3b1c4533853ef833b629e4a -size 69797 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-en-GB.Recovery-incomplete.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-en-GB.Recovery-incomplete.png deleted file mode 100644 index b12b8c297b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-en-GB.Recovery-incomplete.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d76310dce12e1bf7c3b9822d579e68ce85157e9f169f4ac2ed60e366a8e1575d -size 45486 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-pseudo.Both-setup.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-pseudo.Both-setup.png deleted file mode 100644 index 6283779e9b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-pseudo.Both-setup.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2cc5cfa299883fcc4669daa3563dd64e60a4def77d0dc4fa9a2ba0d9c8e4ed6f -size 73180 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-pseudo.Key-backup-disabled.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-pseudo.Key-backup-disabled.png deleted file mode 100644 index b094b2c17b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-pseudo.Key-backup-disabled.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d79c978514d4931150ab3d8cab2093779c9b2b9778cc3f80bd66916ce50ccac1 -size 62313 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-pseudo.Only-key-backup-setup.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-pseudo.Only-key-backup-setup.png deleted file mode 100644 index deed22bfe4..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-pseudo.Only-key-backup-setup.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5f783af792e8f85c3bee7bd00b9e2238cc3f01a3aa1f9db752b39c8f35bcb29f -size 97394 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-pseudo.Recovery-incomplete.png b/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-pseudo.Recovery-incomplete.png deleted file mode 100644 index d212e8939a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_secureBackupScreen-iPhone-15-pseudo.Recovery-incomplete.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6bd6e88c7962bcb17f1934cac6d0d491029c299876172ef8c5027c2c7a4ad093 -size 53699 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-en-GB.Login.png b/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-en-GB.Login.png deleted file mode 100644 index db6d3c8a9c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-en-GB.Login.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:54c9378d347a614b99ecbdfc726e40b6c3a45ee0c65dfb2cd844a57d4c082120 -size 103275 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-en-GB.Register.png b/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-en-GB.Register.png deleted file mode 100644 index ba44dc52d7..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-en-GB.Register.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7d6bce08230f5d53acd5876d2a271eef226221d67c0d9b54d0da9c508f4a50e7 -size 109247 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-pseudo.Login.png b/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-pseudo.Login.png deleted file mode 100644 index 942d258255..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-pseudo.Login.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8abecfd736612e6de8a0f7aa000deaec7e82b6a1ec6a0e8ea7b2111b90400cc3 -size 120427 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-pseudo.Register.png b/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-pseudo.Register.png deleted file mode 100644 index 276b1d7a77..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPad-pseudo.Register.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4282432b52acdd9e97ba0bcf757d9fa5452340c38b833a32a67781a61820bf5b -size 133708 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-15-en-GB.Login.png b/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-15-en-GB.Login.png deleted file mode 100644 index 20f761e9df..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-15-en-GB.Login.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3b2835b33f94b33264877d5464c076b728a6659e6c113f60eabc0dc55a21d37a -size 63563 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-15-en-GB.Register.png b/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-15-en-GB.Register.png deleted file mode 100644 index 155f69a866..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-15-en-GB.Register.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b51b51127ca08cb2187c6addc423160bcc86d97ec0d3334c3c5f5f7b80070cdd -size 68667 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-15-pseudo.Login.png b/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-15-pseudo.Login.png deleted file mode 100644 index e7711dd821..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-15-pseudo.Login.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7bf9a9b5a5eacda0f573517c99446cec54eecb896957d0b67c70ad0f23dbd8d7 -size 87505 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-15-pseudo.Register.png b/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-15-pseudo.Register.png deleted file mode 100644 index 2381711ee3..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_serverConfirmationScreen-iPhone-15-pseudo.Register.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:589d9ea1c5cd46c558a8978204c7674dca980c0a6ad6548af2b7d69e8d88ccad -size 98288 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.1.png deleted file mode 100644 index 091143a7c5..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:da20d1774f6be79338c435917dc36394d4be19311a77d251da1cda8f15670eeb -size 116219 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.2.png b/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.2.png deleted file mode 100644 index 90717fc7f3..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e46770b24f188e4d48d372747f6fbf0ec56b0796e71535f37be09e5670d018ed -size 113708 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.3.png b/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.3.png deleted file mode 100644 index a31d9e8b5b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.3.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:60feac368311b8ec563aed78357028036ea92eaeb0f9e1ed35d5f656ddffe7a0 -size 105000 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.4.png b/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.4.png deleted file mode 100644 index 7b28c84c14..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.4.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4dc7f69072f6f4b49388724785f5aae68544f09374853b09f8bef92fc6dcd47c -size 111656 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.1.png deleted file mode 100644 index fdae7008ec..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:94981c1874260666dd0bc62fa9cbd2d818be40e73efd70a82021a3015d00db43 -size 136144 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.2.png b/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.2.png deleted file mode 100644 index a9a44c7f8a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a203a33107d04f00d8ddf90c93db7ef644a40749847dcd0236ff1136ec95a720 -size 133680 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.3.png b/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.3.png deleted file mode 100644 index afc5f3a83d..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.3.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:42007fd5f1c256c7a6fcc10b4776849f99053252cc5c17fa34c9411fc3bff23d -size 113996 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.4.png b/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.4.png deleted file mode 100644 index 9d32dd215d..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.4.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6e0bbe4f66b7885fe5885f23398e5174facac937ea63b22d7ab9c568d9152601 -size 131977 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Cancelled.png b/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Cancelled.png deleted file mode 100644 index a08a3d9056..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Cancelled.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:426774415058525089bc20ce69af8a1ab721bf5c56c7961c66d0d9d3de808a68 -size 94375 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Request-Accepted.png b/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Request-Accepted.png deleted file mode 100644 index 947638a3d5..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Request-Accepted.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b7354a5eb5bfad07f0161391496f441e14952368b9d5975b5a3f1bed29ccf07a -size 93223 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Requesting-Verification.png b/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Requesting-Verification.png deleted file mode 100644 index ff35a76a61..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Requesting-Verification.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1012f46e630e538a3ca06ce653aaf7425e3eb0cfe09a44e087656808d8532ec1 -size 95644 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Showing-Challenge.png b/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Showing-Challenge.png deleted file mode 100644 index a6f2bbd824..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Showing-Challenge.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:19d04243124ef3964c7060489ea85e5665242fd9be217ca9f3891887575e4886 -size 166134 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Verified.png b/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Verified.png deleted file mode 100644 index 4c331ca61d..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Verified.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b759fac0d53a1a8399c3dbd97037546b9a2b3fc2d906efc67549473543dd77e8 -size 95132 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Cancelled.png b/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Cancelled.png deleted file mode 100644 index 15f5d9f72a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Cancelled.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6c30ea848afc23e3321e7235c804b640438f58f30d97f39d2803027bb433f6c8 -size 106378 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Request-Accepted.png b/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Request-Accepted.png deleted file mode 100644 index 7330a2c5c9..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Request-Accepted.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8c2184a99242de034683603c43444a548f6236414cba75b9a3b7460269f73756 -size 103093 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Requesting-Verification.png b/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Requesting-Verification.png deleted file mode 100644 index ad7ee02224..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Requesting-Verification.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3432349071723eb8e57ec7a082dd5b68bbaaa8845f8fb2d61f1cc7f61fc2553a -size 106890 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Showing-Challenge.png b/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Showing-Challenge.png deleted file mode 100644 index 648929a19b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Showing-Challenge.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b71fdbae9e29a980562d0c7a8f931fdd50514bf0f96da956eb3fb913c253b8d7 -size 185472 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Verified.png b/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Verified.png deleted file mode 100644 index 3468ac26f5..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Verified.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6b335b9f7797cdacd60a3a622655679cc29ba9ade23ef3b348a8a32f112a7bc0 -size 111523 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-en-GB.Cancelled.png b/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-en-GB.Cancelled.png deleted file mode 100644 index b1df94eec6..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-en-GB.Cancelled.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f9a6c9292f4f9fd3164d7d5822934419e6b588ef0771edadf19b2723d13a9e8d -size 52789 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-en-GB.Request-Accepted.png b/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-en-GB.Request-Accepted.png deleted file mode 100644 index 11a51646f3..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-en-GB.Request-Accepted.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:30c800d6a0aad751e9d0f7badd7296f25dd63f969179d5321dcfa2c9395ce3d7 -size 50849 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-en-GB.Requesting-Verification.png b/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-en-GB.Requesting-Verification.png deleted file mode 100644 index 367e1ee438..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-en-GB.Requesting-Verification.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:73809fce6d56738abd975dab2c870a645ebe7770c4d73f9059ec1aa1db986952 -size 52350 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-en-GB.Showing-Challenge.png b/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-en-GB.Showing-Challenge.png deleted file mode 100644 index 998659c8e5..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-en-GB.Showing-Challenge.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1d6e07ee32709a5041592685b72931460353731af602acc01d99f743e82d9743 -size 115776 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-en-GB.Verified.png b/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-en-GB.Verified.png deleted file mode 100644 index b3eeba13a4..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-en-GB.Verified.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c466770faaf6417d48297b20d22db0a60622a8e61259ab2dc5cb79e21f692973 -size 52366 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-pseudo.Cancelled.png b/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-pseudo.Cancelled.png deleted file mode 100644 index 4c64e90927..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-pseudo.Cancelled.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:531d21b6892b1300a722e64984f72bc3e6e960fe9c9cee16d27c4a5c1fa4e366 -size 71690 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-pseudo.Request-Accepted.png b/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-pseudo.Request-Accepted.png deleted file mode 100644 index d1d0f77f11..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-pseudo.Request-Accepted.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9f522b6780c4f60bef86f30b4f7798ac6bddfa4578ce1808c6e286ddf7ce02bb -size 61481 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-pseudo.Requesting-Verification.png b/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-pseudo.Requesting-Verification.png deleted file mode 100644 index 006fad9ff8..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-pseudo.Requesting-Verification.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f61e27e0e4ff1ed3fe8bcf6fb0a0ed62b43527015b7ea7dd304bf2eb88f692b1 -size 69382 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-pseudo.Showing-Challenge.png b/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-pseudo.Showing-Challenge.png deleted file mode 100644 index 26a361399a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-pseudo.Showing-Challenge.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ab9a8d5bbec40bba040819c03fc09f07b3524f6e8e46c6c0cbe70bca18258074 -size 136393 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-pseudo.Verified.png b/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-pseudo.Verified.png deleted file mode 100644 index 07a640e71d..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-15-pseudo.Verified.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1a2e37d0bf721ca476201593651b2d64a3c155e1ff340d485f07ff5604f7eab8 -size 72206 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_settingsScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_settingsScreen-iPad-en-GB.1.png deleted file mode 100644 index aa489c1c88..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_settingsScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3e5c825d5ed31fa05047c973d512e15d19e30840959115f821511587181a7c34 -size 165789 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_settingsScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_settingsScreen-iPad-pseudo.1.png deleted file mode 100644 index 6b9a9d66f9..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_settingsScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d367574abb9dd564373e2a701bff79b38a966ae58fe0d9ca2148bacd093a7369 -size 183521 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_settingsScreen-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_settingsScreen-iPhone-15-en-GB.1.png deleted file mode 100644 index 89294a46fe..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_settingsScreen-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b7f982a5b5ef3fa972445a1c8b8f71052a02bb8fcd00284b7767eb3f2e055547 -size 106445 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_settingsScreen-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_settingsScreen-iPhone-15-pseudo.1.png deleted file mode 100644 index c191c5f8a9..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_settingsScreen-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:227b46eab3e664ecb78f40031814589e6cfd0416c9babe8b0a4aaedfc45eabca -size 123175 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_startChatScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_startChatScreen-iPad-en-GB.1.png deleted file mode 100644 index 2fb12c5067..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_startChatScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0157e03b13940c08482373bf0c5936696f6cb3d6b3600f856cb094903657cc3f -size 98612 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_startChatScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_startChatScreen-iPad-pseudo.1.png deleted file mode 100644 index e715702af8..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_startChatScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3b3133f9fdcd3feb53935a0412282ed707f32456db2324ddc6f310045112c0f7 -size 104446 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_startChatScreen-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_startChatScreen-iPhone-15-en-GB.1.png deleted file mode 100644 index d6f4f359e5..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_startChatScreen-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a4d375f600f1e7765fde156060e4fa29d53bf7cbeab6c37fb297acc5c96ae245 -size 51063 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_startChatScreen-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_startChatScreen-iPhone-15-pseudo.1.png deleted file mode 100644 index 3139487b0d..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_startChatScreen-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ca65a36815c710027cdaa0df608e6b711cbf19e1de76e0a1c27be3f6adec8be3 -size 58790 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-en-GB.Picker.png b/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-en-GB.Picker.png deleted file mode 100644 index 46588abb26..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-en-GB.Picker.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b6a8fa95990af62e81aac8d2944f585bb8ff561d42496e3379816d47c0f92ef0 -size 96251 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-en-GB.View-Only-with-description.png b/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-en-GB.View-Only-with-description.png deleted file mode 100644 index a8816cedbf..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-en-GB.View-Only-with-description.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9397b7bb27f320e1b04b2edc017f138472c9f9c9fc77e6fb789501bc875f7195 -size 93511 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-en-GB.View-Only.png b/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-en-GB.View-Only.png deleted file mode 100644 index a791655fe1..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-en-GB.View-Only.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2a65f13cc87fcf43e0beaa8c48c9ed06262b2623d6671f61f89940bd0e513365 -size 90229 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-pseudo.Picker.png b/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-pseudo.Picker.png deleted file mode 100644 index 0086bf07a6..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-pseudo.Picker.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:18e5e080992a5c4f355031f26573eeace531407ce5cbd0fec559f3a14c438f7e -size 98843 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-pseudo.View-Only-with-description.png b/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-pseudo.View-Only-with-description.png deleted file mode 100644 index b8bd1c264d..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-pseudo.View-Only-with-description.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3ac831619f3eb9ab5ebddb44c08550e7c1114893303994305945838a21adfb8b -size 94235 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-pseudo.View-Only.png b/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-pseudo.View-Only.png deleted file mode 100644 index 92491936cd..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPad-pseudo.View-Only.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ff4fe534df75b19cb4efe8a08155c98120749c28e4c80f4c4d12cddbbca41a93 -size 90937 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-15-en-GB.Picker.png b/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-15-en-GB.Picker.png deleted file mode 100644 index 944182a5dd..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-15-en-GB.Picker.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4d960a2997852d912f18b4bb36d376d6296ae1923bddc6ce087fa624b24383ff -size 53389 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-15-en-GB.View-Only-with-description.png b/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-15-en-GB.View-Only-with-description.png deleted file mode 100644 index c482e93bb3..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-15-en-GB.View-Only-with-description.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:454210631141e70c300f5374df3ec3eae56cff6d6356b9ef5db56796901ed655 -size 50805 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-15-en-GB.View-Only.png b/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-15-en-GB.View-Only.png deleted file mode 100644 index 6ea1c6be15..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-15-en-GB.View-Only.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:96f7d931774d13b52bdda6199715f58aa9c0619fce8c35e7e50c0edf067e3c46 -size 48009 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-15-pseudo.Picker.png b/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-15-pseudo.Picker.png deleted file mode 100644 index 2cf3ead1a3..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-15-pseudo.Picker.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2a4b798eaec69d0544e0240cb0bc11f9164a6a318db2220ea99875bddb859fe9 -size 56113 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-15-pseudo.View-Only-with-description.png b/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-15-pseudo.View-Only-with-description.png deleted file mode 100644 index bf385888d0..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-15-pseudo.View-Only-with-description.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8bcf165d3a1f54313a9523465894efc9bba3dfb4870b160e0eab374ed6d5a951 -size 51490 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-15-pseudo.View-Only.png b/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-15-pseudo.View-Only.png deleted file mode 100644 index 7215f2b17a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_staticLocationScreenViewer-iPhone-15-pseudo.View-Only.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0434fcacfecb731eff967cd3ede8b8252e477582b7113b039be91da8af57bc91 -size 48682 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPad-en-GB.1.png deleted file mode 100644 index 5dc3afdcf2..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:45e913fecbfca17c27d455118c4b0a8adb477966a43f8865936387896859e26f -size 554832 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPad-pseudo.1.png deleted file mode 100644 index 5dc3afdcf2..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:45e913fecbfca17c27d455118c4b0a8adb477966a43f8865936387896859e26f -size 554832 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPhone-15-en-GB.1.png deleted file mode 100644 index 79f80fec5e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:139d1ad264ee618f6dd806f74db0bb09cc5f550ff6c6aec705e63695372200cb -size 476465 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPhone-15-pseudo.1.png deleted file mode 100644 index 79f80fec5e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:139d1ad264ee618f6dd806f74db0bb09cc5f550ff6c6aec705e63695372200cb -size 476465 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_swipeRightAction-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_swipeRightAction-iPad-en-GB.1.png deleted file mode 100644 index 1c09344f8c..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_swipeRightAction-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fbfa5119aab3095ccd04d91804b08e272a308fdc4dd47e40301fc0ed8ea83bc1 -size 82880 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_swipeRightAction-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_swipeRightAction-iPad-pseudo.1.png deleted file mode 100644 index 5f7abe2262..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_swipeRightAction-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:da612a35fad1eceabe352ce649ec5e62d7596bb77d14bc3d5fafcc3d78de06dc -size 83483 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_swipeRightAction-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_swipeRightAction-iPhone-15-en-GB.1.png deleted file mode 100644 index 037ceab6a1..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_swipeRightAction-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5097e52ac3263bf23da8b59044a47b9538e8603e806fbb54e2f1b170325efb48 -size 43900 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_swipeRightAction-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_swipeRightAction-iPhone-15-pseudo.1.png deleted file mode 100644 index 1512242eb3..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_swipeRightAction-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b412c0bcb28ae18d9306a28b2e68a57e1043874caead4e7ab15699af5fc3c24d -size 44582 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Encryption-Indicators.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Encryption-Indicators.png deleted file mode 100644 index b1737febd9..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Encryption-Indicators.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:91293e02a282b89e52d98d10c0ed042e107f58cd661455652c3a50a1295ac9a6 -size 438937 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Thread-decorator.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Thread-decorator.png deleted file mode 100644 index 2b33e3e79a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Thread-decorator.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:28d71dc48e5a4bc8671f67f4b1985ae98dd5f4df1817321bde786f724254cbcf -size 391551 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Encryption-Indicators.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Encryption-Indicators.png deleted file mode 100644 index d2899ca01f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Encryption-Indicators.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d15d0a6e23b80979c7f0025316673e7f20b1b7de6efdf700fb5fc2aebd33a1e2 -size 441049 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Thread-decorator.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Thread-decorator.png deleted file mode 100644 index 54ffd319a0..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Thread-decorator.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b2c46543a0eafef243bbed2b92dd889e7fdcc11dc39a7400f986c90cec47c2f2 -size 396860 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-en-GB.Encryption-Indicators.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-en-GB.Encryption-Indicators.png deleted file mode 100644 index c655b3c0ae..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-en-GB.Encryption-Indicators.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a5a5711cb02a63320e78b0001d014ef7342ab0b6df128af23c836239656cae3b -size 343702 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-en-GB.Thread-decorator.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-en-GB.Thread-decorator.png deleted file mode 100644 index 24cf36e3ff..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-en-GB.Thread-decorator.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b548f6af318563685185a8fe2ab1c59dce4712d88dc23b4d5e0b646e0f254d2f -size 286789 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-pseudo.Encryption-Indicators.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-pseudo.Encryption-Indicators.png deleted file mode 100644 index c427dc3f5b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-pseudo.Encryption-Indicators.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8c8c1c59dd74c9d11e0496583ec9348d1fc7d1eb6504b975eda2e597b3d0fa8f -size 344963 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-pseudo.Thread-decorator.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-pseudo.Thread-decorator.png deleted file mode 100644 index e4ebeb22c3..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-15-pseudo.Thread-decorator.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:98e22ec3f450dfc28e4e556b9b5cb7f41e11f2001029bfc4f668dcf48340e619 -size 288246 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPad-en-GB.1.png deleted file mode 100644 index 2b3606b4f0..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:240231fda2f881caa1157fd2b9e08ebfd531567f083a975914ab20b850e7ce73 -size 113602 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPad-pseudo.1.png deleted file mode 100644 index 3cc1aae969..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9aeb6fa11fabaa24329f86a1c377b6ecd2bce3803442c7ea9b8f79db5e4b9db0 -size 115142 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPhone-15-en-GB.1.png deleted file mode 100644 index 62e94ec625..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:02d646fa0b86b11041fbd1e483339ca7592d36cc4570aab48410ebfd3db5450d -size 69202 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPhone-15-pseudo.1.png deleted file mode 100644 index 9d0fedf9be..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemDebugView-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:13f14e84eb08a205fca317ccdb86d776de4428e623a1db83e8e865449eb2bbd3 -size 70086 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Authenticity-not-guaranteed.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Authenticity-not-guaranteed.png deleted file mode 100644 index 91ab0bee36..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Authenticity-not-guaranteed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4a814e87ba746f5d1590bc620afae3d473eab3497875da9f56fa1f5aceb6b593 -size 139034 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unencrypted.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unencrypted.png deleted file mode 100644 index 4d52e876c5..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unencrypted.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:856395860c1c673ada6ecd4bc1e279fe38d37d6038c4e7cffe6aa885433960d7 -size 132971 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unsigned.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unsigned.png deleted file mode 100644 index f8699c61c0..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unsigned.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:16b0210687ba4e03042cdf79b50bc06e2a866699561228007a6758f03a02a79f -size 136665 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.With-button-shapes-off.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.With-button-shapes-off.png deleted file mode 100644 index 32b2a52828..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.With-button-shapes-off.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0b9ef697532f30ecb4ad0c1ae42cec52c495999da9e2ff238e486be621626692 -size 128275 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.With-button-shapes-on.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.With-button-shapes-on.png deleted file mode 100644 index 7a822bdd67..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.With-button-shapes-on.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b98860688a9a13f02ed226c6db06b208381c0938242b923b24669826ea30ad5c -size 146954 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Authenticity-not-guaranteed.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Authenticity-not-guaranteed.png deleted file mode 100644 index 736724f173..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Authenticity-not-guaranteed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dc5eb6e01de2c2e7b57683ffa0881a300b073c1b0517d96dbc477689e2e4f2e7 -size 146246 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unencrypted.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unencrypted.png deleted file mode 100644 index 3ef3468980..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unencrypted.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f4b4d87745ede48f63c635a517b0b53333248093a12b007f9cb63103eec708f6 -size 137003 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unsigned.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unsigned.png deleted file mode 100644 index d9e0cc4ee1..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unsigned.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d12e1350b1e5a6ec8477feb15fb74e3492fcda98e5802d368110b9289f135475 -size 142260 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.With-button-shapes-off.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.With-button-shapes-off.png deleted file mode 100644 index 2daa634868..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.With-button-shapes-off.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5438bd086e097841f104bd6d6b43b308a2116a8be81253fbef9666267403c26f -size 130069 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.With-button-shapes-on.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.With-button-shapes-on.png deleted file mode 100644 index 743de05282..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.With-button-shapes-on.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d39ea3ad6fe5325875e6449b08c6d5f4c8a56ded6d8b52a2a71aba606af01302 -size 148904 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-en-GB.Authenticity-not-guaranteed.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-en-GB.Authenticity-not-guaranteed.png deleted file mode 100644 index 455ec6afbb..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-en-GB.Authenticity-not-guaranteed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:32ef4ab70c1c611b8022a85855cbc3f0483aeb8b794bc31403dbdeeb417dca3f -size 91903 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-en-GB.Unencrypted.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-en-GB.Unencrypted.png deleted file mode 100644 index 1fa9b5b079..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-en-GB.Unencrypted.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2c14641b3b0bc6d14fefe09eb2e94c273beadd4fb638fd91e13839cb45291dc7 -size 84586 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-en-GB.Unsigned.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-en-GB.Unsigned.png deleted file mode 100644 index 2aaedd1c47..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-en-GB.Unsigned.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:616fc70da47bf61a23cfcaf22928139913dbddab00769dcd2bb3da01a7afc30a -size 87485 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-en-GB.With-button-shapes-off.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-en-GB.With-button-shapes-off.png deleted file mode 100644 index d788ffea9b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-en-GB.With-button-shapes-off.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:babe7ac92847207fe9c42db76a25c443fc056d0cb5236bb74123df1eb1c75fc7 -size 81558 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-en-GB.With-button-shapes-on.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-en-GB.With-button-shapes-on.png deleted file mode 100644 index 71e6dfbab2..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-en-GB.With-button-shapes-on.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b92834dc9f0ea920743fd9336de180eafdc87071209a27e8bd880d21e8e6a39f -size 91943 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-pseudo.Authenticity-not-guaranteed.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-pseudo.Authenticity-not-guaranteed.png deleted file mode 100644 index 89961f7daf..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-pseudo.Authenticity-not-guaranteed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:011c4ce8721d2d12fd159b9451e06f03419543ad6744c7c2ec2f977f46803687 -size 107558 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-pseudo.Unencrypted.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-pseudo.Unencrypted.png deleted file mode 100644 index 844b5fcbde..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-pseudo.Unencrypted.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f77a276e429a2d601cd474e547e3a0923b8b432121b1bb7e12a1eaa593d0d4b6 -size 92034 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-pseudo.Unsigned.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-pseudo.Unsigned.png deleted file mode 100644 index 80b26b3d45..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-pseudo.Unsigned.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8d3cddc2a7fc71a390be380caf341c638ec43950cb7196ecda6ebd58069de750 -size 99561 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-pseudo.With-button-shapes-off.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-pseudo.With-button-shapes-off.png deleted file mode 100644 index 61c99b66fa..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-pseudo.With-button-shapes-off.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8bdb7a577de87f2e99570feda71222da953c4321e3a681c62d0d80b6079cdf81 -size 87175 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-pseudo.With-button-shapes-on.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-pseudo.With-button-shapes-on.png deleted file mode 100644 index 01685ac153..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-15-pseudo.With-button-shapes-on.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5d2ba9cfa065c63a2e62df7ed84bf4838cb01b29124b70a6c9a220d8c037cc50 -size 97569 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineReactionView-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineReactionView-iPad-en-GB.1.png deleted file mode 100644 index 6fc0e54a3e..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineReactionView-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d2c8b076fe62f64ceaa55e3428e7604023eaf31e54990b017854d906744c264f -size 159226 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineReactionView-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineReactionView-iPad-pseudo.1.png deleted file mode 100644 index c8b00b4554..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineReactionView-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:08abbb7a1484c47ca3dd61b48d3793c28cc28491dfba788fad3bcf92412e70d9 -size 150451 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineReactionView-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineReactionView-iPhone-15-en-GB.1.png deleted file mode 100644 index 3ca9a2c4d9..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineReactionView-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:060e9295e901e10489e5be8c2e9ab3aaa15f5145b50846d881224c7034697cfd -size 106466 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineReactionView-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineReactionView-iPhone-15-pseudo.1.png deleted file mode 100644 index ab1c73011b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineReactionView-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fc416e4c7eb992af3d0066e16ee0402344ba9ba93683f850e79b569f39d091b3 -size 98608 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineView-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineView-iPad-en-GB.1.png deleted file mode 100644 index beae942c9b..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineView-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6067114ea694604ada52f8661d19c13093c9ca57fd0bd9dd76a61c22823287fc -size 295821 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineView-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineView-iPad-pseudo.1.png deleted file mode 100644 index 6a6cc62275..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineView-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:28f4aaac85bf4cec7d6ed18b3c7048dc4399c21c18b6d2ad4e3a16c0c1b27517 -size 297798 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineView-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineView-iPhone-15-en-GB.1.png deleted file mode 100644 index 58a32cb823..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineView-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:71180fc6e87efaa6811757379240288bab23f51f609869169acbc26a39ba0214 -size 180340 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_timelineView-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_timelineView-iPhone-15-pseudo.1.png deleted file mode 100644 index 5c0375c809..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_timelineView-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9cd928134ee5d2aec167aef061ab03f764dac009d274227e43342fc8369e23f4 -size 178335 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPad-en-GB.1.png deleted file mode 100644 index 36b5c28858..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:995e46ef39e4a06843bebe718892ae27de7f678bca7c4932915157454f945f9e -size 102981 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPad-pseudo.1.png deleted file mode 100644 index 8b63f8162a..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6946f9bc9476f20e6b2a5c51975fef5d93043d9f8db638cdf4def711abbf2752 -size 106963 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPhone-15-en-GB.1.png deleted file mode 100644 index 15f8d7deeb..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0782e29d565bd7247b8a2c81f14ec166d770553f316ce55e752304831a7b529c -size 54671 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPhone-15-pseudo.1.png deleted file mode 100644 index 1a6bd931d5..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:25afb4070f7fea12943226e25606732390db62da931db97977b6dfd0e6a431cf -size 58017 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-en-GB.No-progress.png b/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-en-GB.No-progress.png deleted file mode 100644 index 1d55a827ea..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-en-GB.No-progress.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c8bec4be82de8edd9c7d875a89c0a1c407b8219233766fe20960c7c16daa2564 -size 90444 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-en-GB.Progress-Bar.png b/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-en-GB.Progress-Bar.png deleted file mode 100644 index 52ac330fbf..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-en-GB.Progress-Bar.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a84218bb2759c3981d29a28879d6f151f8b84c86de5d58e385e856c072294547 -size 91351 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-en-GB.Spinner.png b/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-en-GB.Spinner.png deleted file mode 100644 index a6929e1c52..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-en-GB.Spinner.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:45aafda97d31df92b32aac83e1937f9a082de4cb268bfb903fcca3ea146cbadd -size 92701 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-pseudo.No-progress.png b/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-pseudo.No-progress.png deleted file mode 100644 index 1d55a827ea..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-pseudo.No-progress.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c8bec4be82de8edd9c7d875a89c0a1c407b8219233766fe20960c7c16daa2564 -size 90444 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-pseudo.Progress-Bar.png b/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-pseudo.Progress-Bar.png deleted file mode 100644 index 52ac330fbf..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-pseudo.Progress-Bar.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a84218bb2759c3981d29a28879d6f151f8b84c86de5d58e385e856c072294547 -size 91351 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-pseudo.Spinner.png b/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-pseudo.Spinner.png deleted file mode 100644 index a6929e1c52..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPad-pseudo.Spinner.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:45aafda97d31df92b32aac83e1937f9a082de4cb268bfb903fcca3ea146cbadd -size 92701 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-15-en-GB.No-progress.png b/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-15-en-GB.No-progress.png deleted file mode 100644 index a89c86f610..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-15-en-GB.No-progress.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bf2f20f315ea807d21a10e2ea4b23c613efb0b17852709ec9d22d62b605f5f55 -size 42618 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-15-en-GB.Progress-Bar.png b/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-15-en-GB.Progress-Bar.png deleted file mode 100644 index 128c1a4a19..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-15-en-GB.Progress-Bar.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4b2183177ea97b91da13d0274a1c26373eb15edf4f96cffd3e93bc823a5e7a2b -size 42555 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-15-en-GB.Spinner.png b/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-15-en-GB.Spinner.png deleted file mode 100644 index 32f101d4fe..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-15-en-GB.Spinner.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2665ed968197c341c034bb3e0acc319504ff7a7504a8e0fcd9c48c3e6c2acdea -size 43345 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-15-pseudo.No-progress.png b/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-15-pseudo.No-progress.png deleted file mode 100644 index a89c86f610..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-15-pseudo.No-progress.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bf2f20f315ea807d21a10e2ea4b23c613efb0b17852709ec9d22d62b605f5f55 -size 42618 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-15-pseudo.Progress-Bar.png b/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-15-pseudo.Progress-Bar.png deleted file mode 100644 index 128c1a4a19..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-15-pseudo.Progress-Bar.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4b2183177ea97b91da13d0274a1c26373eb15edf4f96cffd3e93bc823a5e7a2b -size 42555 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-15-pseudo.Spinner.png b/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-15-pseudo.Spinner.png deleted file mode 100644 index 32f101d4fe..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorModalView-iPhone-15-pseudo.Spinner.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2665ed968197c341c034bb3e0acc319504ff7a7504a8e0fcd9c48c3e6c2acdea -size 43345 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPad-en-GB.1.png deleted file mode 100644 index b38ff39ffa..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3458ccde6798b060ab07561d2126bdf577429d7c18860dad31ad7bd33867f594 -size 98589 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPad-pseudo.1.png deleted file mode 100644 index b38ff39ffa..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3458ccde6798b060ab07561d2126bdf577429d7c18860dad31ad7bd33867f594 -size 98589 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPhone-15-en-GB.1.png deleted file mode 100644 index aea34d1ee0..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e0234bfa53c93c48b2890b7a51abc46291a20976b68737448d1c632d92a5588c -size 54634 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPhone-15-pseudo.1.png deleted file mode 100644 index aea34d1ee0..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_userIndicatorToastView-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e0234bfa53c93c48b2890b7a51abc46291a20976b68737448d1c632d92a5588c -size 54634 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPad-en-GB.1.png deleted file mode 100644 index 038f9c5e0f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPad-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cd3b3ad512b4fcd3bf9c4822f3332f61a23a20a880f791ca6693aaeb5ad8b3f0 -size 81295 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPad-pseudo.1.png deleted file mode 100644 index 038f9c5e0f..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPad-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cd3b3ad512b4fcd3bf9c4822f3332f61a23a20a880f791ca6693aaeb5ad8b3f0 -size 81295 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPhone-15-en-GB.1.png deleted file mode 100644 index e85e3fd8dc..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPhone-15-en-GB.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d4c247516251a85727f948204a18127bce75f5aa7a640ca0248ecfc4d09eecd7 -size 40156 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPhone-15-pseudo.1.png deleted file mode 100644 index e85e3fd8dc..0000000000 --- a/PreviewTests/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPhone-15-pseudo.1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d4c247516251a85727f948204a18127bce75f5aa7a640ca0248ecfc4d09eecd7 -size 40156 diff --git a/README.md b/README.md index a2fffb23c3..d9ad55c092 100644 --- a/README.md +++ b/README.md @@ -49,8 +49,8 @@ Please read our [forking guide](docs/FORKING.md). Copyright (c) 2022 - 2024 New Vector Ltd -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with the License. You may obtain a copy of the License in the [LICENSE](LICENSE) file, or at: +Licensed under the AGPL-3.0-only (the "License"); you may not use this work except in compliance with the License. You may obtain a copy of the License in the LICENSE file, or at: -[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) +https://www.gnu.org/licenses/agpl-3.0.txt Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/TchapX/SupportingFiles/target-development.yml b/TchapX/SupportingFiles/target-development.yml new file mode 100644 index 0000000000..4bbbea41a9 --- /dev/null +++ b/TchapX/SupportingFiles/target-development.yml @@ -0,0 +1,226 @@ +name: TchapX-Development + +schemes: + TchapX-Development: + analyze: + config: Debug + archive: + config: Release + build: + targets: + TchapX-Development: + - running + - testing + - profiling + - analyzing + - archiving + profile: + config: Release + run: + config: Debug + environmentVariables: + - variable: HTTPS_PROXY + value: localhost:9090 + isEnabled: false + - variable: UI_TESTS_SCREEN + value: "" + isEnabled: false + - variable: RESET_APP_SETTINGS + value: "true" + isEnabled: false + test: + config: Debug + gatherCoverageData: true + coverageTargets: + - TchapX-Development + testPlans: + - path: ../../UnitTests/SupportingFiles/UnitTests.xctestplan + defaultPlan: true + +targets: + TchapX-Development: + type: application + platform: iOS + + configFiles: + Debug: ../development/SupportingFiles/secrets.xcconfig + Release: ../development/SupportingFiles/secrets.xcconfig + + info: + path: ../development/SupportingFiles/Info.plist + properties: + UILaunchScreen: + UIColorName: colors/background-color + CFBundleDisplayName: $(APP_DISPLAY_NAME) + CFBundleShortVersionString: $(MARKETING_VERSION) + CFBundleVersion: $(CURRENT_PROJECT_VERSION) + CFBundleURLTypes: [ + { + CFBundleTypeRole: Editor, + CFBundleURLName: "Element Call", + CFBundleURLSchemes: [ + io.element.call + ] + }, + { + CFBundleTypeRole: Editor, + CFBundleURLName: "Application", + CFBundleURLSchemes: [ + io.element + ] + } + ] + UISupportedInterfaceOrientations: [ + UIInterfaceOrientationPortrait, + UIInterfaceOrientationPortraitUpsideDown, + UIInterfaceOrientationLandscapeLeft, + UIInterfaceOrientationLandscapeRight + ] + appGroupIdentifier: $(APP_GROUP_IDENTIFIER) + baseBundleIdentifier: $(BASE_BUNDLE_IDENTIFIER) + keychainAccessGroupIdentifier: $(KEYCHAIN_ACCESS_GROUP_IDENTIFIER) + productionAppName: $(PRODUCTION_APP_NAME) + ITSAppUsesNonExemptEncryption: false + NSUserActivityTypes: [ + INSendMessageIntent, + INStartCallIntent, + ] + NSCameraUsageDescription: To take pictures or videos and send them as a message $(APP_DISPLAY_NAME) needs access to the camera. + NSMicrophoneUsageDescription: To record and send messages with audio, $(APP_DISPLAY_NAME) needs to access the microphone. + NSPhotoLibraryAddUsageDescription: Allows saving photos and videos to your library. + NSLocationWhenInUseUsageDescription: Grant location access so that $(APP_DISPLAY_NAME) can share your location. + NSFaceIDUsageDescription: Face ID is used to access your app. + UIBackgroundModes: [ + audio, + fetch, + processing, + voip + ] + BGTaskSchedulerPermittedIdentifiers: [ + io.element.elementx.background.refresh + ] + UTExportedTypeDeclarations: + - UTTypeConformsTo: [public.text] + UTTypeDescription: Mention Pills + UTTypeIdentifier: $(PILLS_UT_TYPE_IDENTIFIER) + CFBundleDocumentTypes: + - CFBundleTypeName: Mention Pills + CFBundleTypeRole: Viewer + LSHandlerRank: Owner + LSItemContentTypes: $(PILLS_UT_TYPE_IDENTIFIER) + LSSupportsOpeningDocumentsInPlace: false + mapLibreAPIKey: $(MAPLIBRE_API_KEY) + + settings: + base: + PRODUCTION_APP_NAME: Tchap DEVELOPMENT + BASE_APP_GROUP_IDENTIFIER: fr.gouv.tchapx.dev + BASE_BUNDLE_IDENTIFIER: fr.gouv.tchapx.dev + APP_NAME: TchapX-development + APP_DISPLAY_NAME: TchapX-DEVELOPMENT + ASSETCATALOG_COMPILER_APPICON_NAME: TchapX-icon + + PRODUCT_NAME: $(APP_NAME) + PRODUCT_BUNDLE_IDENTIFIER: $(BASE_BUNDLE_IDENTIFIER) + CODE_SIGN_ENTITLEMENTS: TchapX/development/SupportingFiles/tchapx.entitlements + 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 + OTHER_SWIFT_FLAGS: + - "-DIS_MAIN_APP -DIS_ENVIRONMENT_DEVELOPMENT" + + + preBuildScripts: + - name: ๐Ÿ›  SwiftGen + runOnlyWhenInstalling: false + basedOnDependencyAnalysis: false + shell: /bin/sh + script: | + export PATH="$PATH:/opt/homebrew/bin" + if which swiftgen >/dev/null; then + swiftgen config run --config Tools/SwiftGen/swiftgen-config.yml + else + echo "warning: SwiftGen not installed, download from https://github.com/SwiftGen/SwiftGen" + fi + - name: ๐Ÿง™ Sourcery - Generate mocks + runOnlyWhenInstalling: false + basedOnDependencyAnalysis: false + shell: /bin/sh + script: | + export PATH="$PATH:/opt/homebrew/bin" + if which sourcery >/dev/null; then + sourcery --config Tools/Sourcery/AutoMockableConfig.yml + else + echo "warning: Sourcery not installed, run swift run tools setup-project" + fi + + postBuildScripts: + - name: โš ๏ธ SwiftLint + runOnlyWhenInstalling: false + basedOnDependencyAnalysis: false + shell: /bin/sh + script: | + export PATH="$PATH:/opt/homebrew/bin" + if which swiftlint >/dev/null; then + swiftlint + else + echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint" + fi + - name: ๐Ÿงน SwiftFormat + runOnlyWhenInstalling: false + basedOnDependencyAnalysis: false + shell: /bin/sh + script: | + export PATH="$PATH:/opt/homebrew/bin" + if which swiftformat >/dev/null; then + swiftformat --lint --lenient "$PROJECT_DIR" + else + echo "warning: SwiftFormat not installed, download from https://github.com/nicklockwood/SwiftFormat" + fi + + dependencies: + - target: NSE-Development + # not used yet + # - target: NCE + - package: MatrixRustSDK + - package: Compound + - package: Algorithms + - package: AnalyticsEvents + - package: Collections + - package: DeviceKit + - package: DTCoreText + - package: KeychainAccess + - package: Kingfisher + - package: KZFileWatchers + - package: LoremSwiftum + - package: LRUCache + - package: Mapbox + - package: PostHog + - package: SwiftState + - package: GZIP + - package: Sentry + products: + - Sentry + - SentrySwiftUI + - package: Version + - package: Emojibase + - package: WysiwygComposer + - package: SwiftOGG + - package: DSWaveformImage + product: DSWaveformImageViews + + sources: + - path: ../../ElementX/Sources + excludes: + - Other/Extensions/XCUIElement.swift + - path: ../main/Sources + excludes: + - Other/Extensions/XCUIElement.swift + - path: ../../ElementX/Resources + - path: ../../ElementX/SupportingFiles/Settings.bundle + - path: ../development/Resources + - path: ../development/SupportingFiles + excludes: + - target.yml + - NSE + - path: ../../Tools/Scripts/Templates/SimpleScreenExample/ElementX \ No newline at end of file diff --git a/TchapX/SupportingFiles/target-production.yml b/TchapX/SupportingFiles/target-production.yml new file mode 100644 index 0000000000..83d9c7cfa1 --- /dev/null +++ b/TchapX/SupportingFiles/target-production.yml @@ -0,0 +1,225 @@ +name: TchapX-Production + +schemes: + TchapX-Production: + analyze: + config: Debug + archive: + config: Release + build: + targets: + TchapX-Production: + - running + - testing + - profiling + - analyzing + - archiving + profile: + config: Release + run: + config: Debug + environmentVariables: + - variable: HTTPS_PROXY + value: localhost:9090 + isEnabled: false + - variable: UI_TESTS_SCREEN + value: "" + isEnabled: false + - variable: RESET_APP_SETTINGS + value: "true" + isEnabled: false + test: + config: Debug + gatherCoverageData: true + coverageTargets: + - TchapX-Production + testPlans: + - path: ../../UnitTests/SupportingFiles/UnitTests.xctestplan + defaultPlan: true + +targets: + TchapX-Production: + type: application + platform: iOS + + configFiles: + Debug: ../production/SupportingFiles/secrets.xcconfig + Release: ../production/SupportingFiles/secrets.xcconfig + + info: + path: ../production/SupportingFiles/Info.plist + properties: + UILaunchScreen: + UIColorName: colors/background-color + CFBundleDisplayName: $(APP_DISPLAY_NAME) + CFBundleShortVersionString: $(MARKETING_VERSION) + CFBundleVersion: $(CURRENT_PROJECT_VERSION) + CFBundleURLTypes: [ + { + CFBundleTypeRole: Editor, + CFBundleURLName: "Element Call", + CFBundleURLSchemes: [ + io.element.call + ] + }, + { + CFBundleTypeRole: Editor, + CFBundleURLName: "Application", + CFBundleURLSchemes: [ + io.element + ] + } + ] + UISupportedInterfaceOrientations: [ + UIInterfaceOrientationPortrait, + UIInterfaceOrientationPortraitUpsideDown, + UIInterfaceOrientationLandscapeLeft, + UIInterfaceOrientationLandscapeRight + ] + appGroupIdentifier: $(APP_GROUP_IDENTIFIER) + baseBundleIdentifier: $(BASE_BUNDLE_IDENTIFIER) + keychainAccessGroupIdentifier: $(KEYCHAIN_ACCESS_GROUP_IDENTIFIER) + productionAppName: $(PRODUCTION_APP_NAME) + ITSAppUsesNonExemptEncryption: false + NSUserActivityTypes: [ + INSendMessageIntent, + INStartCallIntent, + ] + NSCameraUsageDescription: To take pictures or videos and send them as a message $(APP_DISPLAY_NAME) needs access to the camera. + NSMicrophoneUsageDescription: To record and send messages with audio, $(APP_DISPLAY_NAME) needs to access the microphone. + NSPhotoLibraryAddUsageDescription: Allows saving photos and videos to your library. + NSLocationWhenInUseUsageDescription: Grant location access so that $(APP_DISPLAY_NAME) can share your location. + NSFaceIDUsageDescription: Face ID is used to access your app. + UIBackgroundModes: [ + audio, + fetch, + processing, + voip + ] + BGTaskSchedulerPermittedIdentifiers: [ + io.element.elementx.background.refresh + ] + UTExportedTypeDeclarations: + - UTTypeConformsTo: [public.text] + UTTypeDescription: Mention Pills + UTTypeIdentifier: $(PILLS_UT_TYPE_IDENTIFIER) + CFBundleDocumentTypes: + - CFBundleTypeName: Mention Pills + CFBundleTypeRole: Viewer + LSHandlerRank: Owner + LSItemContentTypes: $(PILLS_UT_TYPE_IDENTIFIER) + LSSupportsOpeningDocumentsInPlace: false + mapLibreAPIKey: $(MAPLIBRE_API_KEY) + + settings: + base: + PRODUCTION_APP_NAME: Tchap PRODUCTION + BASE_APP_GROUP_IDENTIFIER: fr.gouv.tchapx + BASE_BUNDLE_IDENTIFIER: fr.gouv.tchapx + APP_NAME: TchapX-production + APP_DISPLAY_NAME: TchapX-PRODUCTION + + PRODUCT_NAME: $(APP_NAME) + PRODUCT_BUNDLE_IDENTIFIER: $(BASE_BUNDLE_IDENTIFIER) + ASSETCATALOG_COMPILER_APPICON_NAME: TchapX-icon + CODE_SIGN_ENTITLEMENTS: TchapX/production/SupportingFiles/tchapx.entitlements + 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 + OTHER_SWIFT_FLAGS: + - "-DIS_MAIN_APP -DIS_ENVIRONMENT_PRODUCTION" + + preBuildScripts: + - name: ๐Ÿ›  SwiftGen + runOnlyWhenInstalling: false + basedOnDependencyAnalysis: false + shell: /bin/sh + script: | + export PATH="$PATH:/opt/homebrew/bin" + if which swiftgen >/dev/null; then + swiftgen config run --config Tools/SwiftGen/swiftgen-config.yml + else + echo "warning: SwiftGen not installed, download from https://github.com/SwiftGen/SwiftGen" + fi + - name: ๐Ÿง™ Sourcery - Generate mocks + runOnlyWhenInstalling: false + basedOnDependencyAnalysis: false + shell: /bin/sh + script: | + export PATH="$PATH:/opt/homebrew/bin" + if which sourcery >/dev/null; then + sourcery --config Tools/Sourcery/AutoMockableConfig.yml + else + echo "warning: Sourcery not installed, run swift run tools setup-project" + fi + + postBuildScripts: + - name: โš ๏ธ SwiftLint + runOnlyWhenInstalling: false + basedOnDependencyAnalysis: false + shell: /bin/sh + script: | + export PATH="$PATH:/opt/homebrew/bin" + if which swiftlint >/dev/null; then + swiftlint + else + echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint" + fi + - name: ๐Ÿงน SwiftFormat + runOnlyWhenInstalling: false + basedOnDependencyAnalysis: false + shell: /bin/sh + script: | + export PATH="$PATH:/opt/homebrew/bin" + if which swiftformat >/dev/null; then + swiftformat --lint --lenient "$PROJECT_DIR" + else + echo "warning: SwiftFormat not installed, download from https://github.com/nicklockwood/SwiftFormat" + fi + + dependencies: + - target: NSE-Production + # not used yet + # - target: NCE + - package: MatrixRustSDK + - package: Compound + - package: Algorithms + - package: AnalyticsEvents + - package: Collections + - package: DeviceKit + - package: DTCoreText + - package: KeychainAccess + - package: Kingfisher + - package: KZFileWatchers + - package: LoremSwiftum + - package: LRUCache + - package: Mapbox + - package: PostHog + - package: SwiftState + - package: GZIP + - package: Sentry + products: + - Sentry + - SentrySwiftUI + - package: Version + - package: Emojibase + - package: WysiwygComposer + - package: SwiftOGG + - package: DSWaveformImage + product: DSWaveformImageViews + + sources: + - path: ../../ElementX/Sources + excludes: + - Other/Extensions/XCUIElement.swift + - path: ../main/Sources + excludes: + - Other/Extensions/XCUIElement.swift + - path: ../../ElementX/Resources + - path: ../../ElementX/SupportingFiles/Settings.bundle + - path: ../production/Resources + - path: ../production/SupportingFiles + excludes: + - target.yml + - NSE + - path: ../../Tools/Scripts/Templates/SimpleScreenExample/ElementX \ No newline at end of file diff --git a/TchapX/SupportingFiles/target-staging.yml b/TchapX/SupportingFiles/target-staging.yml new file mode 100644 index 0000000000..dda3b5ba3d --- /dev/null +++ b/TchapX/SupportingFiles/target-staging.yml @@ -0,0 +1,225 @@ +name: TchapX-Staging + +schemes: + TchapX-Staging: + analyze: + config: Debug + archive: + config: Release + build: + targets: + TchapX-Staging: + - running + - testing + - profiling + - analyzing + - archiving + profile: + config: Release + run: + config: Debug + environmentVariables: + - variable: HTTPS_PROXY + value: localhost:9090 + isEnabled: false + - variable: UI_TESTS_SCREEN + value: "" + isEnabled: false + - variable: RESET_APP_SETTINGS + value: "true" + isEnabled: false + test: + config: Debug + gatherCoverageData: true + coverageTargets: + - TchapX-Staging + testPlans: + - path: ../../UnitTests/SupportingFiles/UnitTests.xctestplan + defaultPlan: true + +targets: + TchapX-Staging: + type: application + platform: iOS + + configFiles: + Debug: ../staging/SupportingFiles/secrets.xcconfig + Release: ../staging/SupportingFiles/secrets.xcconfig + + info: + path: ../staging/SupportingFiles/Info.plist + properties: + UILaunchScreen: + UIColorName: colors/background-color + CFBundleDisplayName: $(APP_DISPLAY_NAME) + CFBundleShortVersionString: $(MARKETING_VERSION) + CFBundleVersion: $(CURRENT_PROJECT_VERSION) + CFBundleURLTypes: [ + { + CFBundleTypeRole: Editor, + CFBundleURLName: "Element Call", + CFBundleURLSchemes: [ + io.element.call + ] + }, + { + CFBundleTypeRole: Editor, + CFBundleURLName: "Application", + CFBundleURLSchemes: [ + io.element + ] + } + ] + UISupportedInterfaceOrientations: [ + UIInterfaceOrientationPortrait, + UIInterfaceOrientationPortraitUpsideDown, + UIInterfaceOrientationLandscapeLeft, + UIInterfaceOrientationLandscapeRight + ] + appGroupIdentifier: $(APP_GROUP_IDENTIFIER) + baseBundleIdentifier: $(BASE_BUNDLE_IDENTIFIER) + keychainAccessGroupIdentifier: $(KEYCHAIN_ACCESS_GROUP_IDENTIFIER) + productionAppName: $(PRODUCTION_APP_NAME) + ITSAppUsesNonExemptEncryption: false + NSUserActivityTypes: [ + INSendMessageIntent, + INStartCallIntent, + ] + NSCameraUsageDescription: To take pictures or videos and send them as a message $(APP_DISPLAY_NAME) needs access to the camera. + NSMicrophoneUsageDescription: To record and send messages with audio, $(APP_DISPLAY_NAME) needs to access the microphone. + NSPhotoLibraryAddUsageDescription: Allows saving photos and videos to your library. + NSLocationWhenInUseUsageDescription: Grant location access so that $(APP_DISPLAY_NAME) can share your location. + NSFaceIDUsageDescription: Face ID is used to access your app. + UIBackgroundModes: [ + audio, + fetch, + processing, + voip + ] + BGTaskSchedulerPermittedIdentifiers: [ + io.element.elementx.background.refresh + ] + UTExportedTypeDeclarations: + - UTTypeConformsTo: [public.text] + UTTypeDescription: Mention Pills + UTTypeIdentifier: $(PILLS_UT_TYPE_IDENTIFIER) + CFBundleDocumentTypes: + - CFBundleTypeName: Mention Pills + CFBundleTypeRole: Viewer + LSHandlerRank: Owner + LSItemContentTypes: $(PILLS_UT_TYPE_IDENTIFIER) + LSSupportsOpeningDocumentsInPlace: false + mapLibreAPIKey: $(MAPLIBRE_API_KEY) + + settings: + base: + PRODUCTION_APP_NAME: Tchap STAGING + BASE_APP_GROUP_IDENTIFIER: fr.gouv.tchapx.staging + BASE_BUNDLE_IDENTIFIER: fr.gouv.tchapx.staging + APP_NAME: TchapX-staging + APP_DISPLAY_NAME: TchapX-STAGING + + PRODUCT_NAME: $(APP_NAME) + PRODUCT_BUNDLE_IDENTIFIER: $(BASE_BUNDLE_IDENTIFIER) + ASSETCATALOG_COMPILER_APPICON_NAME: TchapX-icon + CODE_SIGN_ENTITLEMENTS: TchapX/staging/SupportingFiles/tchapx.entitlements + 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 + OTHER_SWIFT_FLAGS: + - "-DIS_MAIN_APP -DIS_ENVIRONMENT_STAGING" + + preBuildScripts: + - name: ๐Ÿ›  SwiftGen + runOnlyWhenInstalling: false + basedOnDependencyAnalysis: false + shell: /bin/sh + script: | + export PATH="$PATH:/opt/homebrew/bin" + if which swiftgen >/dev/null; then + swiftgen config run --config Tools/SwiftGen/swiftgen-config.yml + else + echo "warning: SwiftGen not installed, download from https://github.com/SwiftGen/SwiftGen" + fi + - name: ๐Ÿง™ Sourcery - Generate mocks + runOnlyWhenInstalling: false + basedOnDependencyAnalysis: false + shell: /bin/sh + script: | + export PATH="$PATH:/opt/homebrew/bin" + if which sourcery >/dev/null; then + sourcery --config Tools/Sourcery/AutoMockableConfig.yml + else + echo "warning: Sourcery not installed, run swift run tools setup-project" + fi + + postBuildScripts: + - name: โš ๏ธ SwiftLint + runOnlyWhenInstalling: false + basedOnDependencyAnalysis: false + shell: /bin/sh + script: | + export PATH="$PATH:/opt/homebrew/bin" + if which swiftlint >/dev/null; then + swiftlint + else + echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint" + fi + - name: ๐Ÿงน SwiftFormat + runOnlyWhenInstalling: false + basedOnDependencyAnalysis: false + shell: /bin/sh + script: | + export PATH="$PATH:/opt/homebrew/bin" + if which swiftformat >/dev/null; then + swiftformat --lint --lenient "$PROJECT_DIR" + else + echo "warning: SwiftFormat not installed, download from https://github.com/nicklockwood/SwiftFormat" + fi + + dependencies: + - target: NSE-Staging + # not used yet + # - target: NCE + - package: MatrixRustSDK + - package: Compound + - package: Algorithms + - package: AnalyticsEvents + - package: Collections + - package: DeviceKit + - package: DTCoreText + - package: KeychainAccess + - package: Kingfisher + - package: KZFileWatchers + - package: LoremSwiftum + - package: LRUCache + - package: Mapbox + - package: PostHog + - package: SwiftState + - package: GZIP + - package: Sentry + products: + - Sentry + - SentrySwiftUI + - package: Version + - package: Emojibase + - package: WysiwygComposer + - package: SwiftOGG + - package: DSWaveformImage + product: DSWaveformImageViews + + sources: + - path: ../../ElementX/Sources + excludes: + - Other/Extensions/XCUIElement.swift + - path: ../main/Sources + excludes: + - Other/Extensions/XCUIElement.swift + - path: ../../ElementX/Resources + - path: ../../ElementX/SupportingFiles/Settings.bundle + - path: ../staging/Resources + - path: ../staging/SupportingFiles + excludes: + - target.yml + - NSE + - path: ../../Tools/Scripts/Templates/SimpleScreenExample/ElementX \ No newline at end of file diff --git a/TchapX/development/SupportingFiles/NSE/target.yml b/TchapX/development/SupportingFiles/NSE/target.yml index 3389863047..0f78cb4b88 100644 --- a/TchapX/development/SupportingFiles/NSE/target.yml +++ b/TchapX/development/SupportingFiles/NSE/target.yml @@ -40,7 +40,6 @@ targets: - package: DeviceKit - package: DTCoreText - package: LRUCache - - package: Prefire - package: Version info: @@ -77,7 +76,8 @@ targets: sources: - path: ../../../../NSE/Sources - - path: ../../../../ElementX/Sources/Generated + - path: ../../../../ElementX/Sources/Generated/Assets.swift + - path: ../../../../ElementX/Sources/Generated/Strings.swift - path: ../../../../ElementX/Sources/Other/AvatarSize.swift - path: ../../../../ElementX/Sources/Other/Extensions/AttributedString.swift - path: ../../../../ElementX/Sources/Other/Extensions/Bundle.swift @@ -102,6 +102,8 @@ targets: - path: ../../../../ElementX/Sources/Other/TestablePreview.swift - path: ../../../../ElementX/Sources/Other/Pills/PlainMentionBuilder.swift - path: ../../../../ElementX/Sources/Other/Pills/PillConstants.swift + - path: ../../../../ElementX/Sources/Other/CurrentValuePublisher.swift + - path: ../../../../ElementX/Sources/Other/NetworkMonitor - path: ../../../../ElementX/Sources/Services/Keychain/KeychainController.swift - path: ../../../../ElementX/Sources/Services/Keychain/KeychainControllerProtocol.swift - path: ../../../../ElementX/Sources/Services/Media/Provider @@ -109,8 +111,9 @@ targets: - path: ../../../../ElementX/Sources/Services/Notification/Proxy - path: ../../../../ElementX/Sources/Services/Room/RoomSummary/RoomMessageEventStringBuilder.swift - path: ../../../../ElementX/Sources/Services/UserSession/RestorationToken.swift + - path: ../../../../ElementX/Sources/Services/UserSession/SessionDirectories.swift - path: ../../../../ElementX/Sources/Services/ElementCall/ElementCallServiceConstants.swift - path: ../../../../ElementX/Sources/Application/AppSettings.swift - path: ../../../../ElementX/Sources/AppHooks/AppHooks.swift - path: ../../../../ElementX/Sources/AppHooks/Hooks/ClientBuilderHook.swift - - path: ../PrivacyInfo.xcprivacy \ No newline at end of file + - path: ../PrivacyInfo.xcprivacy \ No newline at end of file diff --git a/TchapX/development/SupportingFiles/target.yml b/TchapX/development/SupportingFiles/target.yml deleted file mode 100644 index 380fcd9683..0000000000 --- a/TchapX/development/SupportingFiles/target.yml +++ /dev/null @@ -1,227 +0,0 @@ -name: TchapX-Development - -schemes: - TchapX-Development: - analyze: - config: Debug - archive: - config: Release - build: - targets: - TchapX-Development: - - running - - testing - - profiling - - analyzing - - archiving - profile: - config: Release - run: - config: Debug - environmentVariables: - - variable: HTTPS_PROXY - value: localhost:9090 - isEnabled: false - - variable: UI_TESTS_SCREEN - value: "" - isEnabled: false - - variable: RESET_APP_SETTINGS - value: "true" - isEnabled: false - test: - config: Debug - gatherCoverageData: true - coverageTargets: - - TchapX-Development - testPlans: - - path: ../../../UnitTests/SupportingFiles/UnitTests.xctestplan - defaultPlan: true - -targets: - TchapX-Development: - type: application - platform: iOS - - configFiles: - Debug: ../SupportingFiles/secrets.xcconfig - Release: ../SupportingFiles/secrets.xcconfig - - info: - path: ../SupportingFiles/Info.plist - properties: - UILaunchScreen: - UIColorName: colors/background-color - CFBundleDisplayName: $(APP_DISPLAY_NAME) - CFBundleShortVersionString: $(MARKETING_VERSION) - CFBundleVersion: $(CURRENT_PROJECT_VERSION) - CFBundleURLTypes: [ - { - CFBundleTypeRole: Editor, - CFBundleURLName: "Element Call", - CFBundleURLSchemes: [ - io.element.call - ] - }, - { - CFBundleTypeRole: Editor, - CFBundleURLName: "Application", - CFBundleURLSchemes: [ - io.element - ] - } - ] - UISupportedInterfaceOrientations: [ - UIInterfaceOrientationPortrait, - UIInterfaceOrientationPortraitUpsideDown, - UIInterfaceOrientationLandscapeLeft, - UIInterfaceOrientationLandscapeRight - ] - appGroupIdentifier: $(APP_GROUP_IDENTIFIER) - baseBundleIdentifier: $(BASE_BUNDLE_IDENTIFIER) - keychainAccessGroupIdentifier: $(KEYCHAIN_ACCESS_GROUP_IDENTIFIER) - productionAppName: $(PRODUCTION_APP_NAME) - ITSAppUsesNonExemptEncryption: false - NSUserActivityTypes: [ - INSendMessageIntent, - INStartCallIntent, - ] - NSCameraUsageDescription: To take pictures or videos and send them as a message $(APP_DISPLAY_NAME) needs access to the camera. - NSMicrophoneUsageDescription: To record and send messages with audio, $(APP_DISPLAY_NAME) needs to access the microphone. - NSPhotoLibraryAddUsageDescription: Allows saving photos and videos to your library. - NSLocationWhenInUseUsageDescription: Grant location access so that $(APP_DISPLAY_NAME) can share your location. - NSFaceIDUsageDescription: Face ID is used to access your app. - UIBackgroundModes: [ - audio, - fetch, - processing, - voip - ] - BGTaskSchedulerPermittedIdentifiers: [ - io.element.elementx.background.refresh - ] - UTExportedTypeDeclarations: - - UTTypeConformsTo: [public.text] - UTTypeDescription: Mention Pills - UTTypeIdentifier: $(PILLS_UT_TYPE_IDENTIFIER) - CFBundleDocumentTypes: - - CFBundleTypeName: Mention Pills - CFBundleTypeRole: Viewer - LSHandlerRank: Owner - LSItemContentTypes: $(PILLS_UT_TYPE_IDENTIFIER) - LSSupportsOpeningDocumentsInPlace: false - mapLibreAPIKey: $(MAPLIBRE_API_KEY) - - settings: - base: - PRODUCTION_APP_NAME: Tchap DEVELOPMENT - BASE_APP_GROUP_IDENTIFIER: fr.gouv.tchapx.dev - BASE_BUNDLE_IDENTIFIER: fr.gouv.tchapx.dev - APP_NAME: TchapX-development - APP_DISPLAY_NAME: TchapX-DEVELOPMENT - ASSETCATALOG_COMPILER_APPICON_NAME: TchapX-icon - - PRODUCT_NAME: $(APP_NAME) - PRODUCT_BUNDLE_IDENTIFIER: $(BASE_BUNDLE_IDENTIFIER) - CODE_SIGN_ENTITLEMENTS: TchapX/development/SupportingFiles/tchapx.entitlements - 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 - OTHER_SWIFT_FLAGS: - - "-DIS_MAIN_APP -DIS_ENVIRONMENT_DEVELOPMENT" - - - preBuildScripts: - - name: ๐Ÿ›  SwiftGen - runOnlyWhenInstalling: false - basedOnDependencyAnalysis: false - shell: /bin/sh - script: | - export PATH="$PATH:/opt/homebrew/bin" - if which swiftgen >/dev/null; then - swiftgen config run --config Tools/SwiftGen/swiftgen-config.yml - else - echo "warning: SwiftGen not installed, download from https://github.com/SwiftGen/SwiftGen" - fi - - name: ๐Ÿง™ Sourcery - runOnlyWhenInstalling: false - basedOnDependencyAnalysis: false - shell: /bin/sh - script: | - export PATH="$PATH:/opt/homebrew/bin" - if which sourcery >/dev/null; then - sourcery --config Tools/Sourcery/sourcery_automockable_config.yml - else - echo "warning: Sourcery not installed, run swift run tools setup-project" - fi - - postBuildScripts: - - name: โš ๏ธ SwiftLint - runOnlyWhenInstalling: false - basedOnDependencyAnalysis: false - shell: /bin/sh - script: | - export PATH="$PATH:/opt/homebrew/bin" - if which swiftlint >/dev/null; then - swiftlint - else - echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint" - fi - - name: ๐Ÿงน SwiftFormat - runOnlyWhenInstalling: false - basedOnDependencyAnalysis: false - shell: /bin/sh - script: | - export PATH="$PATH:/opt/homebrew/bin" - if which swiftformat >/dev/null; then - swiftformat --lint --lenient "$PROJECT_DIR" - else - echo "warning: SwiftFormat not installed, download from https://github.com/nicklockwood/SwiftFormat" - fi - - dependencies: - - target: NSE-Development - # not used yet - # - target: NCE - - package: MatrixRustSDK - - package: Compound - - package: Algorithms - - package: AnalyticsEvents - - package: Collections - - package: DeviceKit - - package: DTCoreText - - package: KeychainAccess - - package: Kingfisher - - package: KZFileWatchers - - package: LoremSwiftum - - package: LRUCache - - package: Mapbox - - package: PostHog - - package: SwiftState - - package: GZIP - - package: Sentry - products: - - Sentry - - SentrySwiftUI - - package: Version - - package: Emojibase - - package: WysiwygComposer - - package: Prefire - - package: SwiftOGG - - package: DSWaveformImage - product: DSWaveformImageViews - - sources: - - path: ../../../ElementX/Sources - excludes: - - Other/Extensions/XCUIElement.swift - - path: ../../main/Sources - excludes: - - Other/Extensions/XCUIElement.swift - - path: ../../../ElementX/Resources - - path: ../../../ElementX/SupportingFiles/Settings.bundle - - path: ../Resources - - path: ../SupportingFiles - excludes: - - target.yml - - NSE - - path: ../../../Tools/Scripts/Templates/SimpleScreenExample/ElementX \ No newline at end of file diff --git a/TchapX/production/SupportingFiles/NSE/target.yml b/TchapX/production/SupportingFiles/NSE/target.yml index 90ee8b1f77..0026dd49d1 100644 --- a/TchapX/production/SupportingFiles/NSE/target.yml +++ b/TchapX/production/SupportingFiles/NSE/target.yml @@ -40,7 +40,6 @@ targets: - package: DeviceKit - package: DTCoreText - package: LRUCache - - package: Prefire - package: Version info: @@ -77,7 +76,8 @@ targets: sources: - path: ../../../../NSE/Sources - - path: ../../../../ElementX/Sources/Generated + - path: ../../../../ElementX/Sources/Generated/Assets.swift + - path: ../../../../ElementX/Sources/Generated/Strings.swift - path: ../../../../ElementX/Sources/Other/AvatarSize.swift - path: ../../../../ElementX/Sources/Other/Extensions/AttributedString.swift - path: ../../../../ElementX/Sources/Other/Extensions/Bundle.swift @@ -102,6 +102,8 @@ targets: - path: ../../../../ElementX/Sources/Other/TestablePreview.swift - path: ../../../../ElementX/Sources/Other/Pills/PlainMentionBuilder.swift - path: ../../../../ElementX/Sources/Other/Pills/PillConstants.swift + - path: ../../../../ElementX/Sources/Other/CurrentValuePublisher.swift + - path: ../../../../ElementX/Sources/Other/NetworkMonitor - path: ../../../../ElementX/Sources/Services/Keychain/KeychainController.swift - path: ../../../../ElementX/Sources/Services/Keychain/KeychainControllerProtocol.swift - path: ../../../../ElementX/Sources/Services/Media/Provider @@ -109,8 +111,9 @@ targets: - path: ../../../../ElementX/Sources/Services/Notification/Proxy - path: ../../../../ElementX/Sources/Services/Room/RoomSummary/RoomMessageEventStringBuilder.swift - path: ../../../../ElementX/Sources/Services/UserSession/RestorationToken.swift + - path: ../../../../ElementX/Sources/Services/UserSession/SessionDirectories.swift - path: ../../../../ElementX/Sources/Services/ElementCall/ElementCallServiceConstants.swift - path: ../../../../ElementX/Sources/Application/AppSettings.swift - path: ../../../../ElementX/Sources/AppHooks/AppHooks.swift - path: ../../../../ElementX/Sources/AppHooks/Hooks/ClientBuilderHook.swift - - path: ../PrivacyInfo.xcprivacy \ No newline at end of file + - path: ../PrivacyInfo.xcprivacy \ No newline at end of file diff --git a/TchapX/production/SupportingFiles/target.yml b/TchapX/production/SupportingFiles/target.yml deleted file mode 100644 index b05e1203d2..0000000000 --- a/TchapX/production/SupportingFiles/target.yml +++ /dev/null @@ -1,226 +0,0 @@ -name: TchapX-Production - -schemes: - TchapX-Production: - analyze: - config: Debug - archive: - config: Release - build: - targets: - TchapX-Production: - - running - - testing - - profiling - - analyzing - - archiving - profile: - config: Release - run: - config: Debug - environmentVariables: - - variable: HTTPS_PROXY - value: localhost:9090 - isEnabled: false - - variable: UI_TESTS_SCREEN - value: "" - isEnabled: false - - variable: RESET_APP_SETTINGS - value: "true" - isEnabled: false - test: - config: Debug - gatherCoverageData: true - coverageTargets: - - TchapX-Production - testPlans: - - path: ../../../UnitTests/SupportingFiles/UnitTests.xctestplan - defaultPlan: true - -targets: - TchapX-Production: - type: application - platform: iOS - - configFiles: - Debug: ../SupportingFiles/secrets.xcconfig - Release: ../SupportingFiles/secrets.xcconfig - - info: - path: ../SupportingFiles/Info.plist - properties: - UILaunchScreen: - UIColorName: colors/background-color - CFBundleDisplayName: $(APP_DISPLAY_NAME) - CFBundleShortVersionString: $(MARKETING_VERSION) - CFBundleVersion: $(CURRENT_PROJECT_VERSION) - CFBundleURLTypes: [ - { - CFBundleTypeRole: Editor, - CFBundleURLName: "Element Call", - CFBundleURLSchemes: [ - io.element.call - ] - }, - { - CFBundleTypeRole: Editor, - CFBundleURLName: "Application", - CFBundleURLSchemes: [ - io.element - ] - } - ] - UISupportedInterfaceOrientations: [ - UIInterfaceOrientationPortrait, - UIInterfaceOrientationPortraitUpsideDown, - UIInterfaceOrientationLandscapeLeft, - UIInterfaceOrientationLandscapeRight - ] - appGroupIdentifier: $(APP_GROUP_IDENTIFIER) - baseBundleIdentifier: $(BASE_BUNDLE_IDENTIFIER) - keychainAccessGroupIdentifier: $(KEYCHAIN_ACCESS_GROUP_IDENTIFIER) - productionAppName: $(PRODUCTION_APP_NAME) - ITSAppUsesNonExemptEncryption: false - NSUserActivityTypes: [ - INSendMessageIntent, - INStartCallIntent, - ] - NSCameraUsageDescription: To take pictures or videos and send them as a message $(APP_DISPLAY_NAME) needs access to the camera. - NSMicrophoneUsageDescription: To record and send messages with audio, $(APP_DISPLAY_NAME) needs to access the microphone. - NSPhotoLibraryAddUsageDescription: Allows saving photos and videos to your library. - NSLocationWhenInUseUsageDescription: Grant location access so that $(APP_DISPLAY_NAME) can share your location. - NSFaceIDUsageDescription: Face ID is used to access your app. - UIBackgroundModes: [ - audio, - fetch, - processing, - voip - ] - BGTaskSchedulerPermittedIdentifiers: [ - io.element.elementx.background.refresh - ] - UTExportedTypeDeclarations: - - UTTypeConformsTo: [public.text] - UTTypeDescription: Mention Pills - UTTypeIdentifier: $(PILLS_UT_TYPE_IDENTIFIER) - CFBundleDocumentTypes: - - CFBundleTypeName: Mention Pills - CFBundleTypeRole: Viewer - LSHandlerRank: Owner - LSItemContentTypes: $(PILLS_UT_TYPE_IDENTIFIER) - LSSupportsOpeningDocumentsInPlace: false - mapLibreAPIKey: $(MAPLIBRE_API_KEY) - - settings: - base: - PRODUCTION_APP_NAME: Tchap PRODUCTION - BASE_APP_GROUP_IDENTIFIER: fr.gouv.tchapx - BASE_BUNDLE_IDENTIFIER: fr.gouv.tchapx - APP_NAME: TchapX-production - APP_DISPLAY_NAME: TchapX-PRODUCTION - - PRODUCT_NAME: $(APP_NAME) - PRODUCT_BUNDLE_IDENTIFIER: $(BASE_BUNDLE_IDENTIFIER) - ASSETCATALOG_COMPILER_APPICON_NAME: TchapX-icon - CODE_SIGN_ENTITLEMENTS: TchapX/production/SupportingFiles/tchapx.entitlements - 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 - OTHER_SWIFT_FLAGS: - - "-DIS_MAIN_APP -DIS_ENVIRONMENT_PRODUCTION" - - preBuildScripts: - - name: ๐Ÿ›  SwiftGen - runOnlyWhenInstalling: false - basedOnDependencyAnalysis: false - shell: /bin/sh - script: | - export PATH="$PATH:/opt/homebrew/bin" - if which swiftgen >/dev/null; then - swiftgen config run --config Tools/SwiftGen/swiftgen-config.yml - else - echo "warning: SwiftGen not installed, download from https://github.com/SwiftGen/SwiftGen" - fi - - name: ๐Ÿง™ Sourcery - runOnlyWhenInstalling: false - basedOnDependencyAnalysis: false - shell: /bin/sh - script: | - export PATH="$PATH:/opt/homebrew/bin" - if which sourcery >/dev/null; then - sourcery --config Tools/Sourcery/sourcery_automockable_config.yml - else - echo "warning: Sourcery not installed, run swift run tools setup-project" - fi - - postBuildScripts: - - name: โš ๏ธ SwiftLint - runOnlyWhenInstalling: false - basedOnDependencyAnalysis: false - shell: /bin/sh - script: | - export PATH="$PATH:/opt/homebrew/bin" - if which swiftlint >/dev/null; then - swiftlint - else - echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint" - fi - - name: ๐Ÿงน SwiftFormat - runOnlyWhenInstalling: false - basedOnDependencyAnalysis: false - shell: /bin/sh - script: | - export PATH="$PATH:/opt/homebrew/bin" - if which swiftformat >/dev/null; then - swiftformat --lint --lenient "$PROJECT_DIR" - else - echo "warning: SwiftFormat not installed, download from https://github.com/nicklockwood/SwiftFormat" - fi - - dependencies: - - target: NSE-Production - # not used yet - # - target: NCE - - package: MatrixRustSDK - - package: Compound - - package: Algorithms - - package: AnalyticsEvents - - package: Collections - - package: DeviceKit - - package: DTCoreText - - package: KeychainAccess - - package: Kingfisher - - package: KZFileWatchers - - package: LoremSwiftum - - package: LRUCache - - package: Mapbox - - package: PostHog - - package: SwiftState - - package: GZIP - - package: Sentry - products: - - Sentry - - SentrySwiftUI - - package: Version - - package: Emojibase - - package: WysiwygComposer - - package: Prefire - - package: SwiftOGG - - package: DSWaveformImage - product: DSWaveformImageViews - - sources: - - path: ../../../ElementX/Sources - excludes: - - Other/Extensions/XCUIElement.swift - - path: ../../main/Sources - excludes: - - Other/Extensions/XCUIElement.swift - - path: ../../../ElementX/Resources - - path: ../../../ElementX/SupportingFiles/Settings.bundle - - path: ../Resources - - path: ../SupportingFiles - excludes: - - target.yml - - NSE - - path: ../../../Tools/Scripts/Templates/SimpleScreenExample/ElementX \ No newline at end of file diff --git a/TchapX/staging/SupportingFiles/NSE/target.yml b/TchapX/staging/SupportingFiles/NSE/target.yml index 3fca8dc4fc..b76ac07d48 100644 --- a/TchapX/staging/SupportingFiles/NSE/target.yml +++ b/TchapX/staging/SupportingFiles/NSE/target.yml @@ -40,7 +40,6 @@ targets: - package: DeviceKit - package: DTCoreText - package: LRUCache - - package: Prefire - package: Version info: @@ -77,7 +76,8 @@ targets: sources: - path: ../../../../NSE/Sources - - path: ../../../../ElementX/Sources/Generated + - path: ../../../../ElementX/Sources/Generated/Assets.swift + - path: ../../../../ElementX/Sources/Generated/Strings.swift - path: ../../../../ElementX/Sources/Other/AvatarSize.swift - path: ../../../../ElementX/Sources/Other/Extensions/AttributedString.swift - path: ../../../../ElementX/Sources/Other/Extensions/Bundle.swift @@ -102,6 +102,8 @@ targets: - path: ../../../../ElementX/Sources/Other/TestablePreview.swift - path: ../../../../ElementX/Sources/Other/Pills/PlainMentionBuilder.swift - path: ../../../../ElementX/Sources/Other/Pills/PillConstants.swift + - path: ../../../../ElementX/Sources/Other/CurrentValuePublisher.swift + - path: ../../../../ElementX/Sources/Other/NetworkMonitor - path: ../../../../ElementX/Sources/Services/Keychain/KeychainController.swift - path: ../../../../ElementX/Sources/Services/Keychain/KeychainControllerProtocol.swift - path: ../../../../ElementX/Sources/Services/Media/Provider @@ -109,8 +111,9 @@ targets: - path: ../../../../ElementX/Sources/Services/Notification/Proxy - path: ../../../../ElementX/Sources/Services/Room/RoomSummary/RoomMessageEventStringBuilder.swift - path: ../../../../ElementX/Sources/Services/UserSession/RestorationToken.swift + - path: ../../../../ElementX/Sources/Services/UserSession/SessionDirectories.swift - path: ../../../../ElementX/Sources/Services/ElementCall/ElementCallServiceConstants.swift - path: ../../../../ElementX/Sources/Application/AppSettings.swift - path: ../../../../ElementX/Sources/AppHooks/AppHooks.swift - path: ../../../../ElementX/Sources/AppHooks/Hooks/ClientBuilderHook.swift - - path: ../PrivacyInfo.xcprivacy \ No newline at end of file + - path: ../PrivacyInfo.xcprivacy \ No newline at end of file diff --git a/TchapX/staging/SupportingFiles/target.yml b/TchapX/staging/SupportingFiles/target.yml deleted file mode 100644 index 1cb9116e31..0000000000 --- a/TchapX/staging/SupportingFiles/target.yml +++ /dev/null @@ -1,226 +0,0 @@ -name: TchapX-Staging - -schemes: - TchapX-Staging: - analyze: - config: Debug - archive: - config: Release - build: - targets: - TchapX-Staging: - - running - - testing - - profiling - - analyzing - - archiving - profile: - config: Release - run: - config: Debug - environmentVariables: - - variable: HTTPS_PROXY - value: localhost:9090 - isEnabled: false - - variable: UI_TESTS_SCREEN - value: "" - isEnabled: false - - variable: RESET_APP_SETTINGS - value: "true" - isEnabled: false - test: - config: Debug - gatherCoverageData: true - coverageTargets: - - TchapX-Staging - testPlans: - - path: ../../../UnitTests/SupportingFiles/UnitTests.xctestplan - defaultPlan: true - -targets: - TchapX-Staging: - type: application - platform: iOS - - configFiles: - Debug: ../SupportingFiles/secrets.xcconfig - Release: ../SupportingFiles/secrets.xcconfig - - info: - path: ../SupportingFiles/Info.plist - properties: - UILaunchScreen: - UIColorName: colors/background-color - CFBundleDisplayName: $(APP_DISPLAY_NAME) - CFBundleShortVersionString: $(MARKETING_VERSION) - CFBundleVersion: $(CURRENT_PROJECT_VERSION) - CFBundleURLTypes: [ - { - CFBundleTypeRole: Editor, - CFBundleURLName: "Element Call", - CFBundleURLSchemes: [ - io.element.call - ] - }, - { - CFBundleTypeRole: Editor, - CFBundleURLName: "Application", - CFBundleURLSchemes: [ - io.element - ] - } - ] - UISupportedInterfaceOrientations: [ - UIInterfaceOrientationPortrait, - UIInterfaceOrientationPortraitUpsideDown, - UIInterfaceOrientationLandscapeLeft, - UIInterfaceOrientationLandscapeRight - ] - appGroupIdentifier: $(APP_GROUP_IDENTIFIER) - baseBundleIdentifier: $(BASE_BUNDLE_IDENTIFIER) - keychainAccessGroupIdentifier: $(KEYCHAIN_ACCESS_GROUP_IDENTIFIER) - productionAppName: $(PRODUCTION_APP_NAME) - ITSAppUsesNonExemptEncryption: false - NSUserActivityTypes: [ - INSendMessageIntent, - INStartCallIntent, - ] - NSCameraUsageDescription: To take pictures or videos and send them as a message $(APP_DISPLAY_NAME) needs access to the camera. - NSMicrophoneUsageDescription: To record and send messages with audio, $(APP_DISPLAY_NAME) needs to access the microphone. - NSPhotoLibraryAddUsageDescription: Allows saving photos and videos to your library. - NSLocationWhenInUseUsageDescription: Grant location access so that $(APP_DISPLAY_NAME) can share your location. - NSFaceIDUsageDescription: Face ID is used to access your app. - UIBackgroundModes: [ - audio, - fetch, - processing, - voip - ] - BGTaskSchedulerPermittedIdentifiers: [ - io.element.elementx.background.refresh - ] - UTExportedTypeDeclarations: - - UTTypeConformsTo: [public.text] - UTTypeDescription: Mention Pills - UTTypeIdentifier: $(PILLS_UT_TYPE_IDENTIFIER) - CFBundleDocumentTypes: - - CFBundleTypeName: Mention Pills - CFBundleTypeRole: Viewer - LSHandlerRank: Owner - LSItemContentTypes: $(PILLS_UT_TYPE_IDENTIFIER) - LSSupportsOpeningDocumentsInPlace: false - mapLibreAPIKey: $(MAPLIBRE_API_KEY) - - settings: - base: - PRODUCTION_APP_NAME: Tchap STAGING - BASE_APP_GROUP_IDENTIFIER: fr.gouv.tchapx.staging - BASE_BUNDLE_IDENTIFIER: fr.gouv.tchapx.staging - APP_NAME: TchapX-staging - APP_DISPLAY_NAME: TchapX-STAGING - - PRODUCT_NAME: $(APP_NAME) - PRODUCT_BUNDLE_IDENTIFIER: $(BASE_BUNDLE_IDENTIFIER) - ASSETCATALOG_COMPILER_APPICON_NAME: TchapX-icon - CODE_SIGN_ENTITLEMENTS: TchapX/staging/SupportingFiles/tchapx.entitlements - 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 - OTHER_SWIFT_FLAGS: - - "-DIS_MAIN_APP -DIS_ENVIRONMENT_STAGING" - - preBuildScripts: - - name: ๐Ÿ›  SwiftGen - runOnlyWhenInstalling: false - basedOnDependencyAnalysis: false - shell: /bin/sh - script: | - export PATH="$PATH:/opt/homebrew/bin" - if which swiftgen >/dev/null; then - swiftgen config run --config Tools/SwiftGen/swiftgen-config.yml - else - echo "warning: SwiftGen not installed, download from https://github.com/SwiftGen/SwiftGen" - fi - - name: ๐Ÿง™ Sourcery - runOnlyWhenInstalling: false - basedOnDependencyAnalysis: false - shell: /bin/sh - script: | - export PATH="$PATH:/opt/homebrew/bin" - if which sourcery >/dev/null; then - sourcery --config Tools/Sourcery/sourcery_automockable_config.yml - else - echo "warning: Sourcery not installed, run swift run tools setup-project" - fi - - postBuildScripts: - - name: โš ๏ธ SwiftLint - runOnlyWhenInstalling: false - basedOnDependencyAnalysis: false - shell: /bin/sh - script: | - export PATH="$PATH:/opt/homebrew/bin" - if which swiftlint >/dev/null; then - swiftlint - else - echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint" - fi - - name: ๐Ÿงน SwiftFormat - runOnlyWhenInstalling: false - basedOnDependencyAnalysis: false - shell: /bin/sh - script: | - export PATH="$PATH:/opt/homebrew/bin" - if which swiftformat >/dev/null; then - swiftformat --lint --lenient "$PROJECT_DIR" - else - echo "warning: SwiftFormat not installed, download from https://github.com/nicklockwood/SwiftFormat" - fi - - dependencies: - - target: NSE-Staging - # not used yet - # - target: NCE - - package: MatrixRustSDK - - package: Compound - - package: Algorithms - - package: AnalyticsEvents - - package: Collections - - package: DeviceKit - - package: DTCoreText - - package: KeychainAccess - - package: Kingfisher - - package: KZFileWatchers - - package: LoremSwiftum - - package: LRUCache - - package: Mapbox - - package: PostHog - - package: SwiftState - - package: GZIP - - package: Sentry - products: - - Sentry - - SentrySwiftUI - - package: Version - - package: Emojibase - - package: WysiwygComposer - - package: Prefire - - package: SwiftOGG - - package: DSWaveformImage - product: DSWaveformImageViews - - sources: - - path: ../../../ElementX/Sources - excludes: - - Other/Extensions/XCUIElement.swift - - path: ../../main/Sources - excludes: - - Other/Extensions/XCUIElement.swift - - path: ../../../ElementX/Resources - - path: ../../../ElementX/SupportingFiles/Settings.bundle - - path: ../Resources - - path: ../SupportingFiles - excludes: - - target.yml - - NSE - - path: ../../../Tools/Scripts/Templates/SimpleScreenExample/ElementX \ No newline at end of file diff --git a/Tools/Scripts/Templates/SimpleScreenExample/ElementX/TemplateScreenCoordinator.swift b/Tools/Scripts/Templates/SimpleScreenExample/ElementX/TemplateScreenCoordinator.swift index d61ef99b51..6df6e89f3b 100644 --- a/Tools/Scripts/Templates/SimpleScreenExample/ElementX/TemplateScreenCoordinator.swift +++ b/Tools/Scripts/Templates/SimpleScreenExample/ElementX/TemplateScreenCoordinator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // // periphery:ignore:all - this is just a template remove this comment once generating the final file @@ -51,7 +42,7 @@ final class TemplateScreenCoordinator: CoordinatorProtocol { guard let self else { return } switch action { case .done: - self.actionsSubject.send(.done) + actionsSubject.send(.done) } } .store(in: &cancellables) diff --git a/Tools/Scripts/Templates/SimpleScreenExample/ElementX/TemplateScreenModels.swift b/Tools/Scripts/Templates/SimpleScreenExample/ElementX/TemplateScreenModels.swift index dcd0d4a1c7..3009785a27 100644 --- a/Tools/Scripts/Templates/SimpleScreenExample/ElementX/TemplateScreenModels.swift +++ b/Tools/Scripts/Templates/SimpleScreenExample/ElementX/TemplateScreenModels.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/Tools/Scripts/Templates/SimpleScreenExample/ElementX/TemplateScreenViewModel.swift b/Tools/Scripts/Templates/SimpleScreenExample/ElementX/TemplateScreenViewModel.swift index 73fcbb8705..9e04936122 100644 --- a/Tools/Scripts/Templates/SimpleScreenExample/ElementX/TemplateScreenViewModel.swift +++ b/Tools/Scripts/Templates/SimpleScreenExample/ElementX/TemplateScreenViewModel.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/Tools/Scripts/Templates/SimpleScreenExample/ElementX/TemplateScreenViewModelProtocol.swift b/Tools/Scripts/Templates/SimpleScreenExample/ElementX/TemplateScreenViewModelProtocol.swift index f8cea4a5e4..efe2381968 100644 --- a/Tools/Scripts/Templates/SimpleScreenExample/ElementX/TemplateScreenViewModelProtocol.swift +++ b/Tools/Scripts/Templates/SimpleScreenExample/ElementX/TemplateScreenViewModelProtocol.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/Tools/Scripts/Templates/SimpleScreenExample/ElementX/View/TemplateScreen.swift b/Tools/Scripts/Templates/SimpleScreenExample/ElementX/View/TemplateScreen.swift index 5c9aeaf296..e5f72310a5 100644 --- a/Tools/Scripts/Templates/SimpleScreenExample/ElementX/View/TemplateScreen.swift +++ b/Tools/Scripts/Templates/SimpleScreenExample/ElementX/View/TemplateScreen.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Compound diff --git a/Tools/Scripts/Templates/SimpleScreenExample/Tests/UI/TemplateScreenUITests.swift b/Tools/Scripts/Templates/SimpleScreenExample/Tests/UI/TemplateScreenUITests.swift index 02884c5b18..0262186281 100644 --- a/Tools/Scripts/Templates/SimpleScreenExample/Tests/UI/TemplateScreenUITests.swift +++ b/Tools/Scripts/Templates/SimpleScreenExample/Tests/UI/TemplateScreenUITests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/Tools/Scripts/Templates/SimpleScreenExample/Tests/Unit/TemplateScreenViewModelTests.swift b/Tools/Scripts/Templates/SimpleScreenExample/Tests/Unit/TemplateScreenViewModelTests.swift index fdce7269c5..150747812a 100644 --- a/Tools/Scripts/Templates/SimpleScreenExample/Tests/Unit/TemplateScreenViewModelTests.swift +++ b/Tools/Scripts/Templates/SimpleScreenExample/Tests/Unit/TemplateScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/Tools/Scripts/parsePerformanceMetrics.sh b/Tools/Scripts/parsePerformanceMetrics.sh deleted file mode 100755 index c34f5e39fd..0000000000 --- a/Tools/Scripts/parsePerformanceMetrics.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -# Parses performance metrics from the full report of a IntegrationTest run (do not use xcpretty first!) -# This file can normally be found in `~/Library/Logs/scan/IntegrationTests-IntegrationTests.log` - -# Provide file as $1 -# Provide identifier (eg, date, GITHUB_SHA) as $2 - -echo "Parsing $1 for test results with identifier $2" >&2 - -NOW=`date -u -Iminutes` - -# Find all the measurement lines in the file, then strip out the gumph into a CSV-like format. -grep ".*measured.*values" $1 | sed -e "s/.*Test Case .*-\[//" -e "s/\]' measured \[/,/" -e "s/\].*values: \[/,/" -e "s/\], performance.*//" -e "s/^/$2,/" \ - -e "s/IntegrationTests.PerformanceTests testLoginFlow,Duration .AppLaunch., s/launchPerformance/" \ - -e "s/IntegrationTests.PerformanceTests testLoginFlow,Duration .Login., s/loginPerformance/" \ - -e "s/IntegrationTests.PerformanceTests testLoginFlow,Duration .RoomFlow., s/roomFlowPerformance/" \ - -e "s/IntegrationTests.PerformanceTests testLoginFlow,Duration .FirstRooms., s/firstRoomsPerformance/" \ - -e "s/IntegrationTests.PerformanceTests testLoginFlow,Duration .FirstSync., s/firstSyncPerformance/" \ - -e "s/IntegrationTests.PerformanceTests testLoginFlow,Clock Monotonic Time, s/totalTime/" \ - -e "s/^/$NOW,/" - -# The output should contain fields for the identifier, name, type, unit, then a list of recorded values (normally 5) - -# Put this into a file somewhere for later usage. diff --git a/Tools/Sourcery/sourcery_automockable_config.yml b/Tools/Sourcery/AutoMockableConfig.yml similarity index 100% rename from Tools/Sourcery/sourcery_automockable_config.yml rename to Tools/Sourcery/AutoMockableConfig.yml diff --git a/Tools/Sourcery/PreviewTests.stencil b/Tools/Sourcery/PreviewTests.stencil new file mode 100644 index 0000000000..004564722b --- /dev/null +++ b/Tools/Sourcery/PreviewTests.stencil @@ -0,0 +1,46 @@ +// swiftlint:disable all +// swiftformat:disable all + +import XCTest +@testable import ElementX +{% if argument.mainTarget %} +@testable import {{ argument.mainTarget }} +{% endif %} +{% for import in argument.imports %} +{% if import != "last" %} +import {{ import }} +{% endif %} +{% endfor %} +{% for import in argument.testableImports %} +{% if import != "last" %} +@testable import {{ import }} +{% endif %} +{% endfor %} + +extension PreviewTests { + {% if argument.file %} + + private var file: StaticString { .init(stringLiteral: "{{ argument.file }}") } + {% endif %} + + // MARK: - PreviewProvider + + {% for type in types.types where (type.implements.TestablePreview or type.based.TestablePreview or type|annotated:"TestablePreview") and type.name != "TestablePreview" %} + func test_{{ type.name|lowerFirstLetter|replace:"_Previews", "" }}() { + for preview in {{ type.name }}._allPreviews { + assertSnapshots(matching: preview) + } + } + {%- if not forloop.last %} + + {% endif %} + {% endfor %} + {% if argument.previewsMacros %} + // MARK: - Macros + + {{ argument.previewsMacros }} + {% endif %} +} + +// swiftlint:enable all +// swiftformat:enable all diff --git a/Tools/Sourcery/PreviewTestsConfig.yml b/Tools/Sourcery/PreviewTestsConfig.yml new file mode 100644 index 0000000000..7df9dbca7e --- /dev/null +++ b/Tools/Sourcery/PreviewTestsConfig.yml @@ -0,0 +1,7 @@ +sources: + include: + - ../../ElementX +templates: + - PreviewTests.stencil +output: + ../../PreviewTests/Sources/GeneratedPreviewTests.swift diff --git a/Tools/Sources/BuildSDK.swift b/Tools/Sources/BuildSDK.swift index 1fc35a67d5..7a6346f503 100644 --- a/Tools/Sources/BuildSDK.swift +++ b/Tools/Sources/BuildSDK.swift @@ -47,7 +47,7 @@ struct BuildSDK: ParsableCommand { Run the following command to install them: rustup target add \(missingTargets.joined(separator: " ")) --toolchain nightly - + """ default: return nil diff --git a/Tools/XcodeGen/IDETemplateMacros.plist b/Tools/XcodeGen/IDETemplateMacros.plist index c143a31ed5..e70b6ccb11 100644 --- a/Tools/XcodeGen/IDETemplateMacros.plist +++ b/Tools/XcodeGen/IDETemplateMacros.plist @@ -4,19 +4,10 @@ FILEHEADER -// Copyright ___YEAR___ New Vector Ltd +// Copyright ___YEAR___ New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // \ No newline at end of file diff --git a/UITests/Sources/AppLockSetupUITests.swift b/UITests/Sources/AppLockSetupUITests.swift index 66ac360212..0911636358 100644 --- a/UITests/Sources/AppLockSetupUITests.swift +++ b/UITests/Sources/AppLockSetupUITests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UITests/Sources/AppLockUITests.swift b/UITests/Sources/AppLockUITests.swift index 39249a19c9..1eb076218e 100644 --- a/UITests/Sources/AppLockUITests.swift +++ b/UITests/Sources/AppLockUITests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UITests/Sources/Application.swift b/UITests/Sources/Application.swift index 66e6593c2b..861dc17519 100644 --- a/UITests/Sources/Application.swift +++ b/UITests/Sources/Application.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import SnapshotTesting @@ -19,6 +10,10 @@ import XCTest enum Application { static func launch(_ identifier: UITestsScreenIdentifier, disableTimelineAccessibility: Bool = true) -> XCUIApplication { + if ProcessInfo().environment["RECORD_FAILURES"].map(Bool.init) == true { + XCUIApplication.recordMode = .failed + } + checkEnvironments() let app = XCUIApplication() @@ -37,23 +32,27 @@ enum Application { } private static func checkEnvironments() { - let requirediPhoneSimulator = "iPhone15,4" // iPhone 15 + let requirediPhoneSimulator = "iPhone17,3" // iPhone 16 let requirediPadSimulator = "iPad13,18" // iPad (10th generation) - let requiredOSVersion = 17 + let requiredOSVersion = 18 let osVersion = ProcessInfo().operatingSystemVersion guard osVersion.majorVersion == requiredOSVersion else { fatalError("Switch to iOS \(requiredOSVersion) for these tests.") } - guard let deviceModel = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"], - deviceModel == requirediPhoneSimulator || deviceModel == requirediPadSimulator else { - fatalError("Switch to using \(requirediPhoneSimulator) or \(requirediPadSimulator) for these tests.") + guard let deviceModel = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] else { + fatalError("Unknown simulator.") + } + guard deviceModel == requirediPhoneSimulator || deviceModel == requirediPadSimulator else { + fatalError("Running on \(deviceModel) but we only support \(requirediPhoneSimulator) and \(requirediPadSimulator).") } } } 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 @@ -76,17 +75,17 @@ extension XCUIApplication { snapshot = snapshot.inset(by: insets) } - let failure = verifySnapshot(of: snapshot, - as: .image(precision: precision, - perceptualPrecision: 0.98, - scale: nil), - // use any kind of suffix here to snapshot the same file multiple times and avoid countering on the library side - named: "UI", - testName: snapshotName) + let failure = withSnapshotTesting(record: Self.recordMode) { + verifySnapshot(of: snapshot, + as: .image(precision: precision, + perceptualPrecision: 0.98, + scale: nil), + // use any kind of suffix here to snapshot the same file multiple times and avoid countering on the library side + named: "UI", + testName: snapshotName) + } - if let failure, - !failure.contains("No reference was found on disk."), - !failure.contains("to test against the newly-recorded snapshot") { + if let failure { XCTFail(failure) } } diff --git a/UITests/Sources/AuthenticationFlowCoordinatorUITests.swift b/UITests/Sources/AuthenticationFlowCoordinatorUITests.swift index 0839750c3f..e65b8c7875 100644 --- a/UITests/Sources/AuthenticationFlowCoordinatorUITests.swift +++ b/UITests/Sources/AuthenticationFlowCoordinatorUITests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UITests/Sources/BugReportUITests.swift b/UITests/Sources/BugReportUITests.swift index 6ef5572dd8..03b8ec214c 100644 --- a/UITests/Sources/BugReportUITests.swift +++ b/UITests/Sources/BugReportUITests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UITests/Sources/CreateRoomScreenUITests.swift b/UITests/Sources/CreateRoomScreenUITests.swift index d3ff5c9845..235b1520d5 100644 --- a/UITests/Sources/CreateRoomScreenUITests.swift +++ b/UITests/Sources/CreateRoomScreenUITests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UITests/Sources/LoginScreenUITests.swift b/UITests/Sources/LoginScreenUITests.swift index 47651b20ae..2275e1648a 100644 --- a/UITests/Sources/LoginScreenUITests.swift +++ b/UITests/Sources/LoginScreenUITests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UITests/Sources/PollFormScreenUITests.swift b/UITests/Sources/PollFormScreenUITests.swift index a2f5333880..b2587b7483 100644 --- a/UITests/Sources/PollFormScreenUITests.swift +++ b/UITests/Sources/PollFormScreenUITests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UITests/Sources/RoomMembersListScreenUITests.swift b/UITests/Sources/RoomMembersListScreenUITests.swift index d61139f29a..3bcecdfcfe 100644 --- a/UITests/Sources/RoomMembersListScreenUITests.swift +++ b/UITests/Sources/RoomMembersListScreenUITests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UITests/Sources/RoomRolesAndPermissionsUITests.swift b/UITests/Sources/RoomRolesAndPermissionsUITests.swift index 38be24ed85..262a13fcd7 100644 --- a/UITests/Sources/RoomRolesAndPermissionsUITests.swift +++ b/UITests/Sources/RoomRolesAndPermissionsUITests.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UITests/Sources/RoomScreenUITests.swift b/UITests/Sources/RoomScreenUITests.swift index 5bf0ad5d4d..ea109dfdca 100644 --- a/UITests/Sources/RoomScreenUITests.swift +++ b/UITests/Sources/RoomScreenUITests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UITests/Sources/ServerSelectionUITests.swift b/UITests/Sources/ServerSelectionUITests.swift index 9807dabdb0..f5003421c3 100644 --- a/UITests/Sources/ServerSelectionUITests.swift +++ b/UITests/Sources/ServerSelectionUITests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UITests/Sources/SessionVerificationUITests.swift b/UITests/Sources/SessionVerificationUITests.swift index 358e30f8aa..6c7dd2217f 100644 --- a/UITests/Sources/SessionVerificationUITests.swift +++ b/UITests/Sources/SessionVerificationUITests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UITests/Sources/StartChatScreenUITests.swift b/UITests/Sources/StartChatScreenUITests.swift index 0853f0f7b8..66a8e37c7f 100644 --- a/UITests/Sources/StartChatScreenUITests.swift +++ b/UITests/Sources/StartChatScreenUITests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UITests/Sources/UserSessionScreenTests.swift b/UITests/Sources/UserSessionScreenTests.swift index fc0f0065e6..bb8d05177b 100644 --- a/UITests/Sources/UserSessionScreenTests.swift +++ b/UITests/Sources/UserSessionScreenTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-0-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-0-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/appLockFlow-0-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/appLockFlow-0-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPad-10th-generation-en-GB.UI.png index 9dcac63ef9..34d4bd11ba 100644 --- a/UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3b97c28098ab3c2767259036323b441eea5eaba8c5cfe8c07b7a9344cfde0e0a -size 107155 +oid sha256:6b16d8bffe575dbb20cd9ec78ef4750edcbbe75f7e9726771584b272935a1eff +size 107103 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPad-10th-generation-en-GB.UI.png index 6640f6c710..6e8844768e 100644 --- a/UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fea7bd6f7e0157e97b2dfcfd4880f436c674d9033ae2e092c43a3cce47157977 -size 108328 +oid sha256:7ece1e4397aca92f8394aafdf7495ffeaaec3621bb31cc49cd5645e0b134f11f +size 108257 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPad-10th-generation-en-GB.UI.png index 72fc78f2fc..8e2cc629d8 100644 --- a/UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5774ee38f9485f598a44e0179f342c4545147906c81dd61b9c38baa228c4d715 -size 245208 +oid sha256:907d3be4bef23d70e41249c6b73006309822a8fb4a67e3b06382d2ee803392f3 +size 245970 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-4-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-4-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/appLockFlow-4-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/appLockFlow-4-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-99-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-99-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/appLockFlow-99-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/appLockFlow-99-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-0-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-0-iPad-10th-generation-en-GB.UI.png index 7639d94afa..ad2bbc45cb 100644 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-0-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-0-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aaebaa5ba4875c14c4463f648453ac5eb93d6e5c0ffff0316b4e6e18dc917759 -size 125702 +oid sha256:d1393931862148c41d36d12b95fb9996dfbf699e364bca94bd1a45d4219def66 +size 152836 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-0-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-0-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/appLockSetupFlow-0-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/appLockSetupFlow-0-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-1-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-1-iPad-10th-generation-en-GB.UI.png index 5787af9b8d..3fbb8f6106 100644 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-1-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-1-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29e2303c0874b96078a1c72949c6510a88d97fc97f70762c85700639749edac6 -size 125382 +oid sha256:62ecd0c78e6534aa5f71776e59bce5f0bfcba86cfb1045703f1d47bdecc3803e +size 152483 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-1-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-1-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/appLockSetupFlow-1-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/appLockSetupFlow-1-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPad-10th-generation-en-GB.UI.png index 102c9fef2c..0309dcb73d 100644 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c2684e60cabab2f325fa8bc1e8d3e3e439add5430b4372bfe982561d17d3eac4 -size 138184 +oid sha256:c452ed8a368a75805d97ead98fd3b4121ac7ae6068ab2e07c7d099ab790bbb04 +size 154940 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-4-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-4-iPad-10th-generation-en-GB.UI.png index e0abe3daf5..ceeb2f2930 100644 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-4-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-4-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fbe7c3bb82ea7d29a0ac4a7615db8b7f5e1409b5199653c390d07f1e0d0b31c1 -size 142796 +oid sha256:b8ae9afa40428e53bbd54664131ac3a0aa8d1e1feb91036f4b3cdc2aecea77f0 +size 173162 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-5-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-5-iPad-10th-generation-en-GB.UI.png index ff34977b59..b94c3f891a 100644 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-5-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-5-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:02cc6cf93c35cd66d8dfaa758be8c15b35a405993d5a5b18a3e4d991c2943e42 -size 142394 +oid sha256:80764196f842976b1d05f46ce9274c289931cdd5c7b7ca23a53557201a2bd28d +size 172766 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-99-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-99-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/appLockSetupFlow-99-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/appLockSetupFlow-99-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-0-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-0-iPad-10th-generation-en-GB.UI.png index 8880bcbc79..cb8d352abd 100644 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-0-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-0-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6bb737a0d2b01dc485f2446a37cdfcf02e9d6c55b5eaf22273b8c1a954cafd6e -size 90416 +oid sha256:127197150b68b09042e105b726bac64c59260722e8f6d624fd541071e5b68826 +size 90485 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-0-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-0-iPhone-15-en-GB.UI.png deleted file mode 100644 index 8b11791bb5..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-0-iPhone-15-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:50ae60a5eb84ee7b35f8be98ce9f560f64c61803fe86e7fd331f9b21efe0a3bd -size 91609 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-0-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-0-iPhone-16-en-GB.UI.png new file mode 100644 index 0000000000..10440ee5e2 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-0-iPhone-16-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a9fcbf6d7398bd594a7524a6046075434a70b836ceb1e11249ddcfa6d05f373b +size 93225 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-1-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-1-iPad-10th-generation-en-GB.UI.png index abbbf28478..828513de82 100644 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-1-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-1-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c36a3585f6489ee6def7e14d8129425e725d3632062d4b5c57150d1d50b9cbb7 -size 90065 +oid sha256:f233c22c1f60434d1ad95172e6d6effea6295dda098e98083802cc5eb51cdda1 +size 90096 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-1-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-1-iPhone-15-en-GB.UI.png deleted file mode 100644 index 113de1a2af..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-1-iPhone-15-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fe438546e03195e81286c9e1d1cca2dceec61ac7afcac3b231949adaee61e5f3 -size 91293 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-1-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-1-iPhone-16-en-GB.UI.png new file mode 100644 index 0000000000..74ee6c6b82 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-1-iPhone-16-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:295946af755127d55c16f017001088ec0f8e796b6a5eccd871cf5b8b0155a8c3 +size 92907 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPad-10th-generation-en-GB.UI.png index 1f92260533..52e1293a50 100644 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cd30e6a82b3b0c0b5061139ad5cad51b0124a588a2bac5c37755c0d51a72050c -size 96423 +oid sha256:efbe245aca461954d911e0c67a81c684e390e1730ce4416964490c7ba8213a6e +size 96179 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPhone-15-en-GB.UI.png deleted file mode 100644 index bbf34f5eda..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPhone-15-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bf5539fc00cbceae4c2e27227d7e9daa951c224861f12eee7d098d80ef04c364 -size 93442 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPhone-16-en-GB.UI.png new file mode 100644 index 0000000000..0560e34a44 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPhone-16-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-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowUnlock-iPad-10th-generation-en-GB.UI.png index 5430bbb2ec..1821a898d0 100644 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowUnlock-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowUnlock-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e08db1c88352a838368599fd9aca7ddddec87a40449a06c2d206e815da2a0cd8 -size 115776 +oid sha256:66cb7271423fb9653f290c444cee8b84db8692eeca2d2643739246e84d5a6540 +size 140508 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowUnlock-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowUnlock-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/appLockSetupFlowUnlock-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/appLockSetupFlowUnlock-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/authenticationFlow-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/authenticationFlow-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/authenticationFlow-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/authenticationFlow-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/bugReport-0-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/bugReport-0-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/bugReport-0-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/bugReport-0-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/bugReport-2-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/bugReport-2-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/bugReport-2-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/bugReport-2-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/bugReport-3-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/bugReport-3-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/bugReport-3-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/bugReport-3-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/createPoll-1-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createPoll-1-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/createPoll-1-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/createPoll-1-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/createPoll-2-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createPoll-2-iPad-10th-generation-en-GB.UI.png index 67f786804a..16adadcb2e 100644 --- a/UITests/Sources/__Snapshots__/Application/createPoll-2-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/createPoll-2-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58292c1d9a68bd5971fd96c1c9c0145e1938383fc51f98c4831db41cb310d8a2 -size 198024 +oid sha256:cc0378adcd08c8a81fbf79169cb2980ba8b948f484174e847f274244c33d2a1d +size 191811 diff --git a/UITests/Sources/__Snapshots__/Application/createPoll-2-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createPoll-2-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/createPoll-2-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/createPoll-2-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/createPoll-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createPoll-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/createPoll-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/createPoll-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/createRoom-1-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createRoom-1-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/createRoom-1-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/createRoom-1-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/createRoom-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createRoom-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/createRoom-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/createRoom-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/invites-1-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/invites-1-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/invites-1-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/invites-1-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/invites-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/invites-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/invites-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/invites-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/login-0-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/login-0-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/login-0-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/login-0-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/login-1-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/login-1-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/login-1-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/login-1-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/login-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/login-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/login-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/login-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPad-10th-generation-en-GB.UI.png index b5bd371d1c..f4d5dee0af 100644 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2f276e14d5277452dba8c156ac0919c9386f73078fcf12f13731ac1b1d711540 -size 327731 +oid sha256:2a3cddf27c919a33e268efbc56584e069848b9b8d773bcbce30b8bf9ec56f460 +size 323389 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPhone-15-en-GB.UI.png deleted file mode 100644 index 4a36624870..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPhone-15-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c3f1793388cf6ef7f41c06ee75bacf8666691bc58dbfc3fa0cfaf5ef6d605923 -size 334552 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPhone-16-en-GB.UI.png new file mode 100644 index 0000000000..612652406f --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPhone-16-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-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPad-10th-generation-en-GB.UI.png index da8ed0bfa0..5134b0c0bf 100644 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f6653744daf6c2014ab9e652ad9565eec7dc0edab67704735adee9e0aad48a8b -size 329292 +oid sha256:e31cc2b4c2f0fc0a931ec0a1ba4f8531d0435afa02565cca400c06bef2db9243 +size 328875 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPhone-15-en-GB.UI.png deleted file mode 100644 index 1ede348198..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPhone-15-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2f19d1195da5c2fffa2ed4da45983e2d4734078ffc42b1078adb4fdbfa2be1c9 -size 319244 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPhone-16-en-GB.UI.png new file mode 100644 index 0000000000..d845bb2177 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPhone-16-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0805c9072d8de90ff269e80be6c245d1bff4a0f5dc143d19bfaf59a05b170148 +size 317722 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPad-10th-generation-en-GB.UI.png index c8b7625201..2aa6e0a8a3 100644 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f8f4642b8e6371079ca3e81ea55820264951dd7cbab8997eeb0b9087113360b -size 233502 +oid sha256:5c767089cde753c220be4155f44f5a80596ee2b12d452665e65d1310c2f2782a +size 232850 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPhone-15-en-GB.UI.png deleted file mode 100644 index cac2907ad5..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPhone-15-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9cf2b33540efccf9c5ad3a5d183bda468c4e79f760ecd3e99d4d7fb43eb49c2b -size 331768 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPhone-16-en-GB.UI.png new file mode 100644 index 0000000000..292642f97e --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPhone-16-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-10th-generation-en-GB.UI.png index 72ff5eb453..b023078524 100644 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:22cc5b928fccd1e4fb53018512758b26452e176332172911fff64afdf4053055 -size 336655 +oid sha256:dd7ba6f117201899454d8f013219d246cda951654be4727cc218f5e2ce0a6657 +size 334367 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPhone-15-en-GB.UI.png deleted file mode 100644 index 7c6ed1637a..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPhone-15-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:02ddb5960d8da733b7a732da13e92d59794df1828208f9d118694425b821cae8 -size 346141 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPhone-16-en-GB.UI.png new file mode 100644 index 0000000000..c78df95e32 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPhone-16-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ecca3b6f3357d2e5868224b6005079c33543564d08f1b6c32c5b4cde291183eb +size 341217 diff --git a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPhone-16-en-GB.UI.png 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 index ad441a6fd9..c97d2da1b6 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4cc6a35cfe2614ba55d17f3aecc7336ec1dd48937ee48b719163bc72dac14a2 -size 292215 +oid sha256:a48bca99e1534738c818eb248917411f13faac77ae71ab0870cba794a77af6e9 +size 292335 diff --git a/UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPhone-15-en-GB.UI.png deleted file mode 100644 index 638a4dd889..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPhone-15-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:091843bb18a614544534f0eabd2970a5cd6f775e75591428bd3fed1ac9c74328 -size 374446 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 new file mode 100644 index 0000000000..ef5bf35dd4 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPhone-16-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5eb3e3ca8c28ba9f1e4fcd5b7dcf30d162a98ec3cf8539bb8e60ac8802928bf7 +size 369833 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-0-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-0-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-0-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-0-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-3-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-3-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-3-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-3-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-4-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-4-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-4-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-4-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-5-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-5-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-5-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-5-iPhone-16-en-GB.UI.png 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 index e3ca7d97e6..30bd79d5b0 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df13b73403cb43a3387b8e1115dfe11aa8cc20db677d52018cc3c6b6e1acdac7 -size 110631 +oid sha256:487241ee65b911df1aee81bfa44dadb391fa00934033917aeb848c6e1d6eaa5f +size 109509 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPhone-15-en-GB.UI.png deleted file mode 100644 index f85d5b598e..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPhone-15-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:36b7bbbb3452a4f20b5790b84cb83adecbfcd02f8e9e325db06a22a7c6c74115 -size 185184 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPhone-16-en-GB.UI.png new file mode 100644 index 0000000000..5c51abfbcd --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPhone-16-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1fd4349c47465504cae19187ac770f5f72a9ebd139d6635e88e4f780c3766a88 +size 180406 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPad-10th-generation-en-GB.UI.png index e19a6f9aa7..26adee6218 100644 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f622f1f295430f269b491c0e0c7315066da4a1b051d685503f3e7d50378ab8f5 -size 133877 +oid sha256:1a0011a448b569a6a143de24296b3cf2559fdb485237cc143563bb7f2c9b0798 +size 133652 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPhone-15-en-GB.UI.png deleted file mode 100644 index e2f23f4815..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPhone-15-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1343835253f92915a5b2dad424653ac4d5f2452cb54c3d62725c24e97b08ca33 -size 221532 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPhone-16-en-GB.UI.png new file mode 100644 index 0000000000..9ad65331e0 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPhone-16-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-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPad-10th-generation-en-GB.UI.png index 1e9f2ce96a..4ca9322f85 100644 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2d18075f4a94a090bad610b9c5757105078714560cf9be756e946c83370d71d4 -size 331492 +oid sha256:46a30b63dd8fe655bdd33f2d9d4d2d638bc62f5ddea1d2fddc168b07cf9775d9 +size 330970 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPhone-15-en-GB.UI.png deleted file mode 100644 index 357b69dea2..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPhone-15-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5b55a58018122218861fa16e640108743b174596da8a30912079dc2ed1f5961b -size 344558 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPhone-16-en-GB.UI.png new file mode 100644 index 0000000000..26e12acc16 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPhone-16-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-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPad-10th-generation-en-GB.UI.png index 54465bfeac..5d4ea9ccb2 100644 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3b83ba28613978b60b214de90a73f973a1a4b975f377e6f2e519c38ff231791e -size 132795 +oid sha256:0d0631f21e06cf6571bf6ebd48fb252019747d26695a28629d9dbc33bdc27ffe +size 131673 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPhone-15-en-GB.UI.png deleted file mode 100644 index 292e7ff290..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPhone-15-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:81ecddd245e889c442f43fd429c86a72ec0a125b650f030e2548200e4e692529 -size 216998 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPhone-16-en-GB.UI.png new file mode 100644 index 0000000000..6db7ab36bc --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPhone-16-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d78cbc723080c15e1ae3e5ce518517ac329d11a77e959179c84d275411ed976 +size 212177 diff --git a/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPad-10th-generation-en-GB.UI.png index 7f137089d7..be569943f3 100644 --- a/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:af334f8006806cbc0094512042855df6a951b0e69e0f79b7f26b79e7c98bbb36 -size 178100 +oid sha256:1f5086c2ea0fc8186cfa08deb9293401f5c41315c35376598feb1f47639e65fd +size 178419 diff --git a/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPhone-15-en-GB.UI.png deleted file mode 100644 index 98fce26d83..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPhone-15-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4dc2896ad8f7837fb8e21078379d1d5534e23b87ec8ac8673e7c649ae92fab11 -size 291283 diff --git a/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPhone-16-en-GB.UI.png new file mode 100644 index 0000000000..84e852be2c --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPhone-16-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:21a4406c80a619c4a7f97b39200d565f8cb9d84f47ce4bb8bb847fa3de187c09 +size 286492 diff --git a/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPad-10th-generation-en-GB.UI.png index 56b4d311b5..807392ada3 100644 --- a/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0edf1b14ad149c4754d9214a1a348e96f3150a523cccafa29e7a03221fe138b0 -size 142465 +oid sha256:4b26264c2d7d27954ab7aaa00960f29342555e926f034891f77811fe97d81dca +size 142642 diff --git a/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPhone-15-en-GB.UI.png deleted file mode 100644 index 4758b3d271..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPhone-15-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:711fb928fd51daf4148823c7d8ea7622169d7dfc71ef275a6f62683923aff7e5 -size 233789 diff --git a/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPhone-16-en-GB.UI.png new file mode 100644 index 0000000000..9016d3624b --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPhone-16-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b8d92e74b63fd664d19b8757336b32fe6b01fe7301a30ea591eee0e98e8a99e7 +size 228856 diff --git a/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPad-10th-generation-en-GB.UI.png index 0a094ddc24..ae477b2bba 100644 --- a/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2004db3ddd8d4f8deadb75456693a933216a832d315794757b9c400afbd5a2f5 -size 174944 +oid sha256:328fb6ec2d8637e95a19dc5018198dc2d968fd4f4d03f6ff2b751d22e37f748b +size 175169 diff --git a/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPhone-15-en-GB.UI.png deleted file mode 100644 index 2e411ab93d..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPhone-15-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7d04f489f65c0269b1020b311808833f47a9600a727fef9aa8f0eb63881fe537 -size 287557 diff --git a/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPhone-16-en-GB.UI.png new file mode 100644 index 0000000000..2d5830db65 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPhone-16-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4fce73fbf4e5c70b18fe8cd4c4d0ffbb2507c8da30a34d8eaa5d16513343e6e0 +size 282805 diff --git a/UITests/Sources/__Snapshots__/Application/serverSelection-0-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/serverSelection-0-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/serverSelection-0-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/serverSelection-0-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/serverSelection-1-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/serverSelection-1-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/serverSelection-1-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/serverSelection-1-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/serverSelection-2-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/serverSelection-2-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/serverSelection-2-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/serverSelection-2-iPhone-16-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 index ccdac0b798..e322f42980 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:4215cddf5b541955242d789d6d346cda6fcf85f2bbd9d86956fd0ee26bc05136 -size 86302 +oid sha256:08b4681246a562c90a02a189663a7246fe135d037a7e5a0a1f5b4713a420fea1 +size 86484 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPhone-16-en-GB.UI.png 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 4132a59e3c..bfd9392d6c 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:b85c6e376aec739c6b8c9a8d770a7b1dc38653490359e0abb43d052208856402 -size 85122 +oid sha256:8ab61d812816d065aa8903c69df0459bba1142721cc9eef9e39ba05f7f505b66 +size 85240 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPhone-16-en-GB.UI.png 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 9292891c48..c68a1624dc 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:49b3f48855a40f62ae14edb46f706f21f2f686e520526129017a443d91c8bb2d -size 84425 +oid sha256:21932c55d7c3e55ce291c1ea410011a2b1b9647cd4e90d9295cefb85e74e8025 +size 84710 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPhone-16-en-GB.UI.png 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 76a1215844..8d9fc3b388 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:0d6d1db7cfc9192459ab23f02b7429eae90bc4756e432c6b0c3a023901d95a22 -size 65069 +oid sha256:b58d6f9e5d1a4cc6d337634f96e2731fa9dea1cb128e2634d2ff2dc5858eb98b +size 65167 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPhone-16-en-GB.UI.png 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 459e673d72..50e5dafbc0 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:d4021f5c48aa076aadd7d507fff569b9bebd863b31fac2e13cbd3d2158ec080f -size 147742 +oid sha256:9eff84ef4beab29cd3c652f389efeedd787b0910e83c1b2c2c23c7ebf933150d +size 148382 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPhone-16-en-GB.UI.png 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 a5a1565718..5a41df0546 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:a882a373d2d9e788bf7185917bdea2bf088ea82158c083f72716e60e7cedb735 -size 146416 +oid sha256:ea9b96696dae004c420fc922664dd5d88e0190aaab19a25cc29ee2fe0d1526a7 +size 146760 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPhone-16-en-GB.UI.png 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 be93f60984..fb67410bd6 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:8ed3c01d726e223888b22ad0c4bc5aa76eaa3a4d3731d5f8adfab41058c9b98e -size 85513 +oid sha256:2bff344e5fbc9b9ccb88b22866c511cd51cc6970127955947a54b33dfdcaa5da +size 85667 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPhone-16-en-GB.UI.png 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 ee0263eb6a..e087e3cc4a 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:4e19bfc56a4918a3c494b993084e0a4000f2a043654ac83992a6d17f4099aadb -size 84985 +oid sha256:a154db9b1f771604817d54cc804309eaf80b92ec44632225c11cc9118f2ee6cb +size 85038 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/startChat-1-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/startChat-1-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/startChat-1-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/startChat-1-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/startChat-2-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/startChat-2-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/startChat-2-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/startChat-2-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/startChat-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/startChat-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/startChat-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/startChat-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/templateScreen-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/templateScreen-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/templateScreen-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/templateScreen-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPad-10th-generation-en-GB.UI.png index aaca4d8811..ab91f912e8 100644 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c848c67896ff09355855508ee15ff790e8616f0ccf1f0bc2a09e712ed37f9fa2 -size 320571 +oid sha256:b2f921a9f3613e93a12410d1762e4cba1e557ee47ace34ec43100deeccbd9d40 +size 316350 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPhone-15-en-GB.UI.png deleted file mode 100644 index d11c630844..0000000000 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPhone-15-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5a0233872549045ce33e800d72dcf0a43e025e674d7fc82f315f919799db2cee -size 318030 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPhone-16-en-GB.UI.png new file mode 100644 index 0000000000..1fa07f5f49 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPhone-16-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:672046d4289a23075b82789d5fca2b6b4f1cab3b75147cd2a5eec5d5dd79c398 +size 299984 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPad-10th-generation-en-GB.UI.png index 47adc57486..e4dd9086d8 100644 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c5e8724fcf38fb6510b4f078a6df898a5d64a6e54be5115151a30027132d9166 -size 468430 +oid sha256:4ab055b4aed25baff5715521523bbebd9bf91d563914ebcca885b15a8f6a98de +size 461977 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPhone-16-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPad-10th-generation-en-GB.UI.png index 32f1268b8c..b48dad3f22 100644 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:816b90d1d31fc84e19ef0318d0619d680ab7d3c84987d811ec86b54738a6cf57 -size 753048 +oid sha256:ede54c8caf251097eacab4da82359978233aeb7f9cc5c9e4024894ede70dcf77 +size 746883 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPhone-16-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPhone-15-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPhone-16-en-GB.UI.png 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 index 653eb9b106..2c60f79341 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2309ebb909f73dd4d80501f950985b7b508061f5d1eb95b20d8888b970c77049 -size 471147 +oid sha256:709a17b15a259e2383b97b885597f2815fae10ac81867e78b4de95eb9e23f96d +size 461940 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPhone-15-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPhone-15-en-GB.UI.png deleted file mode 100644 index faeaeec099..0000000000 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPhone-15-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5ba2361eeb3b23d6c2b5932db52b57840be3aa5e57ea8c149aa892db25523313 -size 332161 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 new file mode 100644 index 0000000000..a4ca218e2e --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPhone-16-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0870e0bfa1c8b07a56f03103ed5a1ba4e6a54474c956299f9de5d618fbf4f2aa +size 333096 diff --git a/UITests/SupportingFiles/UITests.xctestplan b/UITests/SupportingFiles/UITests.xctestplan index 3147e6759a..9e927a3c07 100644 --- a/UITests/SupportingFiles/UITests.xctestplan +++ b/UITests/SupportingFiles/UITests.xctestplan @@ -27,6 +27,11 @@ { "key" : "SNAPSHOT_ARTIFACTS", "value" : "\/tmp\/__FailedScreenshots__" + }, + { + "enabled" : false, + "key" : "RECORD_FAILURES", + "value" : "true" } ], "locationScenario" : { diff --git a/UnitTests/Sources/AVMetadataMachineReadableCodeObjectExtensionsTest.swift b/UnitTests/Sources/AVMetadataMachineReadableCodeObjectExtensionsTest.swift index 1dba91e1de..0afd97ff98 100644 --- a/UnitTests/Sources/AVMetadataMachineReadableCodeObjectExtensionsTest.swift +++ b/UnitTests/Sources/AVMetadataMachineReadableCodeObjectExtensionsTest.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import AVKit diff --git a/UnitTests/Sources/AnalyticsSettingsScreenViewModelTests.swift b/UnitTests/Sources/AnalyticsSettingsScreenViewModelTests.swift index fa3c01f209..091c091dec 100644 --- a/UnitTests/Sources/AnalyticsSettingsScreenViewModelTests.swift +++ b/UnitTests/Sources/AnalyticsSettingsScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/AnalyticsTests.swift b/UnitTests/Sources/AnalyticsTests.swift index d38b57bbc3..92837afd3b 100644 --- a/UnitTests/Sources/AnalyticsTests.swift +++ b/UnitTests/Sources/AnalyticsTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import AnalyticsEvents diff --git a/UnitTests/Sources/AppLock/AppLockScreenViewModelTests.swift b/UnitTests/Sources/AppLock/AppLockScreenViewModelTests.swift index 44b8411ea8..e25d9e7b83 100644 --- a/UnitTests/Sources/AppLock/AppLockScreenViewModelTests.swift +++ b/UnitTests/Sources/AppLock/AppLockScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/AppLock/AppLockServiceTests.swift b/UnitTests/Sources/AppLock/AppLockServiceTests.swift index 2084aad3d8..9a1324abce 100644 --- a/UnitTests/Sources/AppLock/AppLockServiceTests.swift +++ b/UnitTests/Sources/AppLock/AppLockServiceTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/AppLock/AppLockSettingsScreenViewModelTests.swift b/UnitTests/Sources/AppLock/AppLockSettingsScreenViewModelTests.swift index 31a09f126f..ab7b242e01 100644 --- a/UnitTests/Sources/AppLock/AppLockSettingsScreenViewModelTests.swift +++ b/UnitTests/Sources/AppLock/AppLockSettingsScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/AppLock/AppLockSetupBiometricsScreenViewModelTests.swift b/UnitTests/Sources/AppLock/AppLockSetupBiometricsScreenViewModelTests.swift index 07fdc17d67..c11e6113c5 100644 --- a/UnitTests/Sources/AppLock/AppLockSetupBiometricsScreenViewModelTests.swift +++ b/UnitTests/Sources/AppLock/AppLockSetupBiometricsScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/AppLock/AppLockSetupPINScreenViewModelTests.swift b/UnitTests/Sources/AppLock/AppLockSetupPINScreenViewModelTests.swift index 9e00868dfd..9363a6b215 100644 --- a/UnitTests/Sources/AppLock/AppLockSetupPINScreenViewModelTests.swift +++ b/UnitTests/Sources/AppLock/AppLockSetupPINScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/AppLock/AppLockTimerTests.swift b/UnitTests/Sources/AppLock/AppLockTimerTests.swift index 633d158c84..5c1e34c21b 100644 --- a/UnitTests/Sources/AppLock/AppLockTimerTests.swift +++ b/UnitTests/Sources/AppLock/AppLockTimerTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/AppLock/PINTextFieldTests.swift b/UnitTests/Sources/AppLock/PINTextFieldTests.swift index 17b14b11bc..e80a74de9a 100644 --- a/UnitTests/Sources/AppLock/PINTextFieldTests.swift +++ b/UnitTests/Sources/AppLock/PINTextFieldTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/AppRouteURLParserTests.swift b/UnitTests/Sources/AppRouteURLParserTests.swift index 76b2378f6d..952e249f80 100644 --- a/UnitTests/Sources/AppRouteURLParserTests.swift +++ b/UnitTests/Sources/AppRouteURLParserTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/ArrayTests.swift b/UnitTests/Sources/ArrayTests.swift index 4d05f5d6dd..5e6c453be1 100644 --- a/UnitTests/Sources/ArrayTests.swift +++ b/UnitTests/Sources/ArrayTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/UnitTests/Sources/AttributedStringBuilderTests.swift b/UnitTests/Sources/AttributedStringBuilderTests.swift index 6b35264b8c..3c9b31bcf8 100644 --- a/UnitTests/Sources/AttributedStringBuilderTests.swift +++ b/UnitTests/Sources/AttributedStringBuilderTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @testable import ElementX diff --git a/UnitTests/Sources/AttributedStringTests.swift b/UnitTests/Sources/AttributedStringTests.swift index a1dad32a25..f78fb7bf87 100644 --- a/UnitTests/Sources/AttributedStringTests.swift +++ b/UnitTests/Sources/AttributedStringTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @testable import ElementX diff --git a/UnitTests/Sources/AudioPlayerStateTests.swift b/UnitTests/Sources/AudioPlayerStateTests.swift index 3488a9a9b4..7761de3a2c 100644 --- a/UnitTests/Sources/AudioPlayerStateTests.swift +++ b/UnitTests/Sources/AudioPlayerStateTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -37,6 +28,7 @@ class AudioPlayerStateTests: XCTestCase { audioPlayerMock.underlyingActions = audioPlayerActions audioPlayerMock.state = .stopped audioPlayerMock.currentTime = 0.0 + audioPlayerMock.duration = 0.0 audioPlayerMock.seekToClosure = { [audioPlayerSeekCallsSubject] progress in audioPlayerSeekCallsSubject?.send(progress) } @@ -46,7 +38,7 @@ class AudioPlayerStateTests: XCTestCase { override func setUp() async throws { audioPlayerActionsSubject = .init() audioPlayerSeekCallsSubject = .init() - audioPlayerState = AudioPlayerState(id: .timelineItemIdentifier(.random), duration: Self.audioDuration) + audioPlayerState = AudioPlayerState(id: .timelineItemIdentifier(.random), title: "", duration: Self.audioDuration) audioPlayerMock = buildAudioPlayerMock() audioPlayerMock.seekToClosure = { [weak self] progress in self?.audioPlayerMock.currentTime = Self.audioDuration * progress @@ -170,7 +162,7 @@ class AudioPlayerStateTests: XCTestCase { func testHandlingAudioPlayerActionDidFinishLoading() async throws { audioPlayerMock.duration = 10.0 - audioPlayerState = AudioPlayerState(id: .timelineItemIdentifier(.random), duration: 0) + audioPlayerState = AudioPlayerState(id: .timelineItemIdentifier(.random), title: "", duration: 0) audioPlayerState.attachAudioPlayer(audioPlayerMock) let deferred = deferFulfillment(audioPlayerState.$playbackState) { action in diff --git a/UnitTests/Sources/AudioRecorderStateTests.swift b/UnitTests/Sources/AudioRecorderStateTests.swift index d456e2932c..aea9216b56 100644 --- a/UnitTests/Sources/AudioRecorderStateTests.swift +++ b/UnitTests/Sources/AudioRecorderStateTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/UnitTests/Sources/AudioRecorderTests.swift b/UnitTests/Sources/AudioRecorderTests.swift index 6bc736c31e..9cd2906692 100644 --- a/UnitTests/Sources/AudioRecorderTests.swift +++ b/UnitTests/Sources/AudioRecorderTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/UnitTests/Sources/AuthenticationStartScreenViewModelTests.swift b/UnitTests/Sources/AuthenticationStartScreenViewModelTests.swift index 1d82b704d7..686b3e508b 100644 --- a/UnitTests/Sources/AuthenticationStartScreenViewModelTests.swift +++ b/UnitTests/Sources/AuthenticationStartScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/BlockedUsersScreenViewModelTests.swift b/UnitTests/Sources/BlockedUsersScreenViewModelTests.swift index 9fe8d82034..c79e725f32 100644 --- a/UnitTests/Sources/BlockedUsersScreenViewModelTests.swift +++ b/UnitTests/Sources/BlockedUsersScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/UnitTests/Sources/BugReportScreenViewModelTests.swift b/UnitTests/Sources/BugReportScreenViewModelTests.swift index 63aa031d3f..72c55d54eb 100644 --- a/UnitTests/Sources/BugReportScreenViewModelTests.swift +++ b/UnitTests/Sources/BugReportScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/BugReportServiceTests.swift b/UnitTests/Sources/BugReportServiceTests.swift index c2d2730cb8..33c2380127 100644 --- a/UnitTests/Sources/BugReportServiceTests.swift +++ b/UnitTests/Sources/BugReportServiceTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @testable import ElementX diff --git a/UnitTests/Sources/CallScreenViewModelTests.swift b/UnitTests/Sources/CallScreenViewModelTests.swift index c7a99ffb51..9582ef38bc 100644 --- a/UnitTests/Sources/CallScreenViewModelTests.swift +++ b/UnitTests/Sources/CallScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/ClientProtocolTests.swift b/UnitTests/Sources/ClientProtocolTests.swift new file mode 100644 index 0000000000..a4e03855c3 --- /dev/null +++ b/UnitTests/Sources/ClientProtocolTests.swift @@ -0,0 +1,70 @@ +// +// Copyright 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 +@testable import MatrixRustSDK + +class ClientProtocolTests: XCTestCase { + let server = "https://matrix.org" + let userIDServerName = "matrix.org" + let wellKnownURL = "https://matrix.org/.well-known/element/element.json" + + var client: ClientProtocol! + + func testWellKnownLoggedOut() async { + // Given a client that is logged out but has discovered a server. + let client = ClientSDKMock() + client.userIdServerNameThrowableError = MockError.notAvailable + client.serverReturnValue = server + + // When discovering a server that contains the registration helper URL. + client.getUrlUrlClosure = { [wellKnownURL] url in + guard url == wellKnownURL else { + XCTFail("An unexpected URL was used.") + throw MockError.notAvailable + } + return "{\"registration_helper_url\":\"https://develop.element.io/#/mobile_register\"}" + } + + guard case let .success(wellKnown) = await client.getElementWellKnown() else { + XCTFail("The request should succeed.") + return + } + + // Then the well-known should include that URL. + XCTAssertEqual(wellKnown, .init(call: nil, registrationHelperUrl: "https://develop.element.io/#/mobile_register")) + } + + func testWellKnownLoggedIn() async { + // Given a client that is logged in. + let client = ClientSDKMock() + client.userIdServerNameReturnValue = userIDServerName + + // When discovering a server that contains a custom call widget URL. + client.getUrlUrlClosure = { [wellKnownURL] url in + guard url == wellKnownURL else { + XCTFail("An unexpected URL was used.") + throw MockError.notAvailable + } + return "{\"call\":{\"widget_url\":\"https://call.element.dev\"}}" + } + + guard case let .success(wellKnown) = await client.getElementWellKnown() else { + XCTFail("The request should succeed.") + return + } + + // Then the well-known should include that URL. + XCTAssertEqual(wellKnown, .init(call: .init(widgetUrl: "https://call.element.dev"), registrationHelperUrl: nil)) + } + + enum MockError: Error { + case notAvailable + } +} diff --git a/UnitTests/Sources/CompletionSuggestionServiceTests.swift b/UnitTests/Sources/CompletionSuggestionServiceTests.swift index 26d555726a..902fdcd9d0 100644 --- a/UnitTests/Sources/CompletionSuggestionServiceTests.swift +++ b/UnitTests/Sources/CompletionSuggestionServiceTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -30,7 +21,7 @@ final class CompletionSuggestionServiceTests: XCTestCase { func testUserSuggestions() async throws { let alice: RoomMemberProxyMock = .mockAlice let members: [RoomMemberProxyMock] = [alice, .mockBob, .mockCharlie, .mockMe] - let roomProxyMock = RoomProxyMock(.init(name: "test", members: members)) + let roomProxyMock = JoinedRoomProxyMock(.init(name: "test", members: members)) let service = CompletionSuggestionService(roomProxy: roomProxyMock) var deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in @@ -67,7 +58,7 @@ final class CompletionSuggestionServiceTests: XCTestCase { func testUserSuggestionsIncludingAllUsers() async throws { let alice: RoomMemberProxyMock = .mockAlice let members: [RoomMemberProxyMock] = [alice, .mockBob, .mockCharlie, .mockMe] - let roomProxyMock = RoomProxyMock(.init(name: "test", members: members, canUserTriggerRoomNotification: true)) + let roomProxyMock = JoinedRoomProxyMock(.init(name: "test", members: members, canUserTriggerRoomNotification: true)) let service = CompletionSuggestionService(roomProxy: roomProxyMock) var deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in @@ -93,7 +84,7 @@ final class CompletionSuggestionServiceTests: XCTestCase { let alice: RoomMemberProxyMock = .mockAlice let bob: RoomMemberProxyMock = .mockBob let members: [RoomMemberProxyMock] = [alice, bob, .mockMe] - let roomProxyMock = RoomProxyMock(.init(name: "test", members: members, canUserTriggerRoomNotification: true)) + let roomProxyMock = JoinedRoomProxyMock(.init(name: "test", members: members, canUserTriggerRoomNotification: true)) let service = CompletionSuggestionService(roomProxy: roomProxyMock) var deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in diff --git a/UnitTests/Sources/ComposerToolbarViewModelTests.swift b/UnitTests/Sources/ComposerToolbarViewModelTests.swift index 8cc1004bc3..162ac0d97f 100644 --- a/UnitTests/Sources/ComposerToolbarViewModelTests.swift +++ b/UnitTests/Sources/ComposerToolbarViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -50,22 +41,22 @@ class ComposerToolbarViewModelTests: XCTestCase { } func testComposerFocus() { - viewModel.process(roomAction: .setMode(mode: .edit(originalItemId: TimelineItemIdentifier(timelineID: "mock")))) + viewModel.process(timelineAction: .setMode(mode: .edit(originalItemId: TimelineItemIdentifier(timelineID: "mock")))) XCTAssertTrue(viewModel.state.bindings.composerFocused) - viewModel.process(roomAction: .removeFocus) + viewModel.process(timelineAction: .removeFocus) XCTAssertFalse(viewModel.state.bindings.composerFocused) } func testComposerMode() { - let mode: RoomScreenComposerMode = .edit(originalItemId: TimelineItemIdentifier(timelineID: "mock")) - viewModel.process(roomAction: .setMode(mode: mode)) + let mode: ComposerMode = .edit(originalItemId: TimelineItemIdentifier(timelineID: "mock")) + viewModel.process(timelineAction: .setMode(mode: mode)) XCTAssertEqual(viewModel.state.composerMode, mode) - viewModel.process(roomAction: .clear) + viewModel.process(timelineAction: .clear) XCTAssertEqual(viewModel.state.composerMode, .default) } func testComposerModeIsPublished() { - let mode: RoomScreenComposerMode = .edit(originalItemId: TimelineItemIdentifier(timelineID: "mock")) + let mode: ComposerMode = .edit(originalItemId: TimelineItemIdentifier(timelineID: "mock")) let expectation = expectation(description: "Composer mode is published") let cancellable = viewModel .context @@ -78,7 +69,7 @@ class ComposerToolbarViewModelTests: XCTestCase { expectation.fulfill() }) - viewModel.process(roomAction: .setMode(mode: mode)) + viewModel.process(timelineAction: .setMode(mode: mode)) wait(for: [expectation], timeout: 2.0) cancellable.cancel() @@ -206,7 +197,7 @@ class ComposerToolbarViewModelTests: XCTestCase { viewModel.context.composerFormattingEnabled = false viewModel.context.plainComposerText = .init(string: "Hello world!") - viewModel.process(roomAction: .saveDraft) + viewModel.saveDraft() await fulfillment(of: [expectation], timeout: 10) XCTAssertEqual(draftServiceMock.saveDraftCallsCount, 1) @@ -226,7 +217,7 @@ class ComposerToolbarViewModelTests: XCTestCase { viewModel.context.composerFormattingEnabled = true wysiwygViewModel.setHtmlContent("Hello world!") - viewModel.process(roomAction: .saveDraft) + viewModel.saveDraft() await fulfillment(of: [expectation], timeout: 10) XCTAssertEqual(draftServiceMock.saveDraftCallsCount, 1) @@ -245,9 +236,9 @@ class ComposerToolbarViewModelTests: XCTestCase { } viewModel.context.composerFormattingEnabled = false - viewModel.process(roomAction: .setMode(mode: .edit(originalItemId: .init(timelineID: "", eventID: "testID")))) + viewModel.process(timelineAction: .setMode(mode: .edit(originalItemId: .init(timelineID: "", eventID: "testID")))) viewModel.context.plainComposerText = .init(string: "Hello world!") - viewModel.process(roomAction: .saveDraft) + viewModel.saveDraft() await fulfillment(of: [expectation], timeout: 10) XCTAssertEqual(draftServiceMock.saveDraftCallsCount, 1) @@ -266,14 +257,14 @@ class ComposerToolbarViewModelTests: XCTestCase { } viewModel.context.composerFormattingEnabled = false - viewModel.process(roomAction: .setMode(mode: .reply(itemID: .init(timelineID: "", - eventID: "testID"), + viewModel.process(timelineAction: .setMode(mode: .reply(itemID: .init(timelineID: "", + eventID: "testID"), replyDetails: .loaded(sender: .init(id: ""), eventID: "testID", eventContent: .message(.text(.init(body: "reply text")))), isThread: false))) viewModel.context.plainComposerText = .init(string: "Hello world!") - viewModel.process(roomAction: .saveDraft) + viewModel.saveDraft() await fulfillment(of: [expectation], timeout: 10) XCTAssertEqual(draftServiceMock.saveDraftCallsCount, 1) @@ -292,13 +283,13 @@ class ComposerToolbarViewModelTests: XCTestCase { } viewModel.context.composerFormattingEnabled = false - viewModel.process(roomAction: .setMode(mode: .reply(itemID: .init(timelineID: "", - eventID: "testID"), + viewModel.process(timelineAction: .setMode(mode: .reply(itemID: .init(timelineID: "", + eventID: "testID"), replyDetails: .loaded(sender: .init(id: ""), eventID: "testID", eventContent: .message(.text(.init(body: "reply text")))), isThread: false))) - viewModel.process(roomAction: .saveDraft) + viewModel.saveDraft() await fulfillment(of: [expectation], timeout: 10) XCTAssertEqual(draftServiceMock.saveDraftCallsCount, 1) @@ -314,7 +305,7 @@ class ComposerToolbarViewModelTests: XCTestCase { } viewModel.context.composerFormattingEnabled = false - viewModel.process(roomAction: .saveDraft) + viewModel.saveDraft() await fulfillment(of: [expectation], timeout: 10) XCTAssertFalse(draftServiceMock.saveDraftCalled) @@ -332,8 +323,10 @@ class ComposerToolbarViewModelTests: XCTestCase { viewModel.context.composerFormattingEnabled = false let waveformData: [Float] = Array(repeating: 1.0, count: 1000) viewModel.context.plainComposerText = .init(string: "Hello world!") - viewModel.process(roomAction: .setMode(mode: .previewVoiceMessage(state: AudioPlayerState(id: .recorderPreview, duration: 10.0), waveform: .data(waveformData), isUploading: false))) - viewModel.process(roomAction: .saveDraft) + viewModel.process(timelineAction: .setMode(mode: .previewVoiceMessage(state: AudioPlayerState(id: .recorderPreview, title: "", duration: 10.0), + waveform: .data(waveformData), + isUploading: false))) + viewModel.saveDraft() await fulfillment(of: [expectation], timeout: 10) XCTAssertFalse(draftServiceMock.saveDraftCalled) @@ -349,7 +342,7 @@ class ComposerToolbarViewModelTests: XCTestCase { return .success(nil) } - viewModel.process(roomAction: .loadDraft) + viewModel.loadDraft() await fulfillment(of: [expectation], timeout: 10) XCTAssertFalse(viewModel.context.composerFormattingEnabled) XCTAssertTrue(viewModel.state.composerEmpty) @@ -365,7 +358,7 @@ class ComposerToolbarViewModelTests: XCTestCase { htmlText: nil, draftType: .newMessage)) } - viewModel.process(roomAction: .loadDraft) + viewModel.loadDraft() await fulfillment(of: [expectation], timeout: 10) XCTAssertFalse(viewModel.context.composerFormattingEnabled) @@ -382,7 +375,7 @@ class ComposerToolbarViewModelTests: XCTestCase { htmlText: "Hello world!", draftType: .newMessage)) } - viewModel.process(roomAction: .loadDraft) + viewModel.loadDraft() await fulfillment(of: [expectation], timeout: 10) XCTAssertTrue(viewModel.context.composerFormattingEnabled) @@ -400,7 +393,7 @@ class ComposerToolbarViewModelTests: XCTestCase { htmlText: nil, draftType: .edit(eventID: "testID"))) } - viewModel.process(roomAction: .loadDraft) + viewModel.loadDraft() await fulfillment(of: [expectation], timeout: 10) XCTAssertFalse(viewModel.context.composerFormattingEnabled) @@ -433,7 +426,7 @@ class ComposerToolbarViewModelTests: XCTestCase { return .success(.init(details: loadedReply, isThreaded: true)) } - viewModel.process(roomAction: .loadDraft) + viewModel.loadDraft() await fulfillment(of: [draftExpectation], timeout: 10) XCTAssertFalse(viewModel.context.composerFormattingEnabled) @@ -474,7 +467,7 @@ class ComposerToolbarViewModelTests: XCTestCase { return .success(.init(details: loadedReply, isThreaded: true)) } - viewModel.process(roomAction: .loadDraft) + viewModel.loadDraft() await fulfillment(of: [draftExpectation], timeout: 10) XCTAssertFalse(viewModel.context.composerFormattingEnabled) @@ -493,7 +486,7 @@ class ComposerToolbarViewModelTests: XCTestCase { func testSaveVolatileDraftWhenEditing() { viewModel.context.composerFormattingEnabled = false viewModel.context.plainComposerText = .init(string: "Hello world!") - viewModel.process(roomAction: .setMode(mode: .edit(originalItemId: .random))) + viewModel.process(timelineAction: .setMode(mode: .edit(originalItemId: .random))) let draft = draftServiceMock.saveVolatileDraftReceivedDraft XCTAssertNotNil(draft) @@ -530,7 +523,7 @@ class ComposerToolbarViewModelTests: XCTestCase { expectation2.fulfill() } - viewModel.process(roomAction: .clear) + viewModel.process(timelineAction: .clear) await fulfillment(of: [expectation1, expectation2]) XCTAssertEqual(viewModel.context.plainComposerText, NSAttributedString(string: "Hello world")) } @@ -549,7 +542,7 @@ class ComposerToolbarViewModelTests: XCTestCase { expectation2.fulfill() } - viewModel.process(roomAction: .clear) + viewModel.process(timelineAction: .clear) await fulfillment(of: [expectation1, expectation2]) XCTAssertEqual(viewModel.context.plainComposerText, NSAttributedString(string: "Hello world")) } @@ -557,7 +550,7 @@ class ComposerToolbarViewModelTests: XCTestCase { func testRestoreUserMentionInPlainText() async throws { viewModel.context.composerFormattingEnabled = false let text = "Hello [TestName](https://matrix.to/#/@test:matrix.org)!" - viewModel.process(roomAction: .setText(plainText: text, htmlText: nil)) + viewModel.process(timelineAction: .setText(plainText: text, htmlText: nil)) let deferred = deferFulfillment(viewModel.actions) { action in switch action { @@ -577,7 +570,7 @@ class ComposerToolbarViewModelTests: XCTestCase { func testRestoreAllUsersMentionInPlainText() async throws { viewModel.context.composerFormattingEnabled = false let text = "Hello @room" - viewModel.process(roomAction: .setText(plainText: text, htmlText: nil)) + viewModel.process(timelineAction: .setText(plainText: text, htmlText: nil)) let deferred = deferFulfillment(viewModel.actions) { action in switch action { @@ -596,7 +589,7 @@ class ComposerToolbarViewModelTests: XCTestCase { func testRestoreMixedMentionsInPlainText() async throws { viewModel.context.composerFormattingEnabled = false let text = "Hello [User1](https://matrix.to/#/@user1:matrix.org), [User2](https://matrix.to/#/@user2:matrix.org) and @room" - viewModel.process(roomAction: .setText(plainText: text, htmlText: nil)) + viewModel.process(timelineAction: .setText(plainText: text, htmlText: nil)) let deferred = deferFulfillment(viewModel.actions) { action in switch action { @@ -616,7 +609,7 @@ class ComposerToolbarViewModelTests: XCTestCase { func testRestoreAmbiguousMention() async throws { viewModel.context.composerFormattingEnabled = false let text = "Hello [User1](https://matrix.to/#/@roomuser:matrix.org)" - viewModel.process(roomAction: .setText(plainText: text, htmlText: nil)) + viewModel.process(timelineAction: .setText(plainText: text, htmlText: nil)) let deferred = deferFulfillment(viewModel.actions) { action in switch action { diff --git a/UnitTests/Sources/CreateRoomViewModelTests.swift b/UnitTests/Sources/CreateRoomViewModelTests.swift index 161a9cb35b..2dc1940e20 100644 --- a/UnitTests/Sources/CreateRoomViewModelTests.swift +++ b/UnitTests/Sources/CreateRoomViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/UnitTests/Sources/DateTests.swift b/UnitTests/Sources/DateTests.swift index e3ce8a9ac7..adb2c4b452 100644 --- a/UnitTests/Sources/DateTests.swift +++ b/UnitTests/Sources/DateTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @testable import ElementX diff --git a/UnitTests/Sources/DeactivateAccountScreenViewModelTests.swift b/UnitTests/Sources/DeactivateAccountScreenViewModelTests.swift new file mode 100644 index 0000000000..2a2946a126 --- /dev/null +++ b/UnitTests/Sources/DeactivateAccountScreenViewModelTests.swift @@ -0,0 +1,81 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import XCTest + +@testable import ElementX + +@MainActor +class DeactivateAccountScreenViewModelTests: XCTestCase { + var clientProxy: ClientProxyMock! + var viewModel: DeactivateAccountScreenViewModelProtocol! + + var context: DeactivateAccountScreenViewModelType.Context { + viewModel.context + } + + override func setUpWithError() throws { + clientProxy = ClientProxyMock(.init()) + viewModel = DeactivateAccountScreenViewModel(clientProxy: clientProxy, userIndicatorController: UserIndicatorControllerMock()) + } + + func testDeactivate() async throws { + try await validateDeactivate(erasingData: false) + } + + func testDeactivateAndErase() async throws { + try await validateDeactivate(erasingData: true) + } + + func validateDeactivate(erasingData shouldErase: Bool) async throws { + let enteredPassword = UUID().uuidString + + clientProxy.deactivateAccountPasswordEraseDataClosure = { [weak self] password, eraseData in + guard let self else { return .failure(.sdkError(ClientProxyMockError.generic)) } + + if clientProxy.deactivateAccountPasswordEraseDataCallsCount == 1 { + if password != nil { + XCTFail("The password shouldn't be sent first time round.") + } + if eraseData != shouldErase { + XCTFail("The erase parameter is unexpected.") + } + return .failure(.sdkError(ClientProxyMockError.generic)) + } else { + if password != enteredPassword { + XCTFail("The password should match the user's input on the second call.") + } + if eraseData != shouldErase { + XCTFail("The erase parameter is unexpected.") + } + return .success(()) + } + } + + context.eraseData = shouldErase + context.password = enteredPassword + + XCTAssertNil(context.alertInfo) + + let deferredState = deferFulfillment(context.$viewState) { $0.bindings.alertInfo != nil } + context.send(viewAction: .deactivate) + try await deferredState.fulfill() + + guard let confirmationAction = context.alertInfo?.primaryButton.action else { + XCTFail("Couldn't find the confirmation action.") + return + } + + let deferredAction = deferFulfillment(viewModel.actionsPublisher) { $0 == .accountDeactivated } + confirmationAction() + try await deferredAction.fulfill() + + XCTAssertEqual(clientProxy.deactivateAccountPasswordEraseDataCallsCount, 2) + XCTAssertEqual(clientProxy.deactivateAccountPasswordEraseDataReceivedArguments?.password, enteredPassword) + XCTAssertEqual(clientProxy.deactivateAccountPasswordEraseDataReceivedArguments?.eraseData, shouldErase) + } +} diff --git a/UnitTests/Sources/DeveloperOptionsScreenViewModelTests.swift b/UnitTests/Sources/DeveloperOptionsScreenViewModelTests.swift index 802b3967e8..e1fd2392de 100644 --- a/UnitTests/Sources/DeveloperOptionsScreenViewModelTests.swift +++ b/UnitTests/Sources/DeveloperOptionsScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/EmojiDetectionTests.swift b/UnitTests/Sources/EmojiDetectionTests.swift index 77f47bfd5c..16c3e188ae 100644 --- a/UnitTests/Sources/EmojiDetectionTests.swift +++ b/UnitTests/Sources/EmojiDetectionTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/EmojiProviderTests.swift b/UnitTests/Sources/EmojiProviderTests.swift index 342e0ba1d8..4733122b8c 100644 --- a/UnitTests/Sources/EmojiProviderTests.swift +++ b/UnitTests/Sources/EmojiProviderTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/ExpiringTaskRunnerTests.swift b/UnitTests/Sources/ExpiringTaskRunnerTests.swift index e5991989ae..4e23ecf58e 100644 --- a/UnitTests/Sources/ExpiringTaskRunnerTests.swift +++ b/UnitTests/Sources/ExpiringTaskRunnerTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/UnitTests/Sources/Extensions/Publisher.swift b/UnitTests/Sources/Extensions/Publisher.swift index cfc8485289..586ec841eb 100644 --- a/UnitTests/Sources/Extensions/Publisher.swift +++ b/UnitTests/Sources/Extensions/Publisher.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/UnitTests/Sources/Extensions/XCTestCase.swift b/UnitTests/Sources/Extensions/XCTestCase.swift index 17802520ca..03ddda4339 100644 --- a/UnitTests/Sources/Extensions/XCTestCase.swift +++ b/UnitTests/Sources/Extensions/XCTestCase.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/UnitTests/Sources/GeoURITests.swift b/UnitTests/Sources/GeoURITests.swift index 750a6e84d2..dd45401e16 100644 --- a/UnitTests/Sources/GeoURITests.swift +++ b/UnitTests/Sources/GeoURITests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @testable import ElementX diff --git a/UnitTests/Sources/GlobalSearchScreenViewModelTests.swift b/UnitTests/Sources/GlobalSearchScreenViewModelTests.swift index 3f796a25fc..40c72f959d 100644 --- a/UnitTests/Sources/GlobalSearchScreenViewModelTests.swift +++ b/UnitTests/Sources/GlobalSearchScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -28,7 +19,7 @@ class GlobalSearchScreenViewModelTests: XCTestCase { override func setUpWithError() throws { cancellables.removeAll() viewModel = GlobalSearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))), - imageProvider: MockMediaProvider()) + mediaProvider: MockMediaProvider()) context = viewModel.context } diff --git a/UnitTests/Sources/HomeScreenRoomTests.swift b/UnitTests/Sources/HomeScreenRoomTests.swift index fa80cf07a8..bb47ffc0ce 100644 --- a/UnitTests/Sources/HomeScreenRoomTests.swift +++ b/UnitTests/Sources/HomeScreenRoomTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/UnitTests/Sources/HomeScreenViewModelTests.swift b/UnitTests/Sources/HomeScreenViewModelTests.swift index f6faa5e956..e485844793 100644 --- a/UnitTests/Sources/HomeScreenViewModelTests.swift +++ b/UnitTests/Sources/HomeScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -87,7 +78,7 @@ class HomeScreenViewModelTests: XCTestCase { func testLeaveRoomAlert() async throws { let mockRoomId = "1" - clientProxy.roomForIdentifierClosure = { _ in RoomProxyMock(.init(id: mockRoomId, name: "Some room")) } + clientProxy.roomForIdentifierClosure = { _ in .joined(JoinedRoomProxyMock(.init(id: mockRoomId, name: "Some room"))) } let deferred = deferFulfillment(context.$viewState) { value in value.bindings.leaveRoomAlertItem != nil @@ -102,10 +93,10 @@ class HomeScreenViewModelTests: XCTestCase { func testLeaveRoomError() async throws { let mockRoomId = "1" - let room = RoomProxyMock(.init(id: mockRoomId, name: "Some room")) + let room = JoinedRoomProxyMock(.init(id: mockRoomId, name: "Some room")) room.leaveRoomClosure = { .failure(.sdkError(ClientProxyMockError.generic)) } - clientProxy.roomForIdentifierClosure = { _ in room } + clientProxy.roomForIdentifierClosure = { _ in .joined(room) } let deferred = deferFulfillment(context.$viewState) { value in value.bindings.alertInfo != nil @@ -133,10 +124,10 @@ class HomeScreenViewModelTests: XCTestCase { expectation.fulfill() } .store(in: &cancellables) - let room = RoomProxyMock(.init(id: mockRoomId, name: "Some room")) + let room = JoinedRoomProxyMock(.init(id: mockRoomId, name: "Some room")) room.leaveRoomClosure = { .success(()) } - clientProxy.roomForIdentifierClosure = { _ in room } + clientProxy.roomForIdentifierClosure = { _ in .joined(room) } context.send(viewAction: .confirmLeaveRoom(roomIdentifier: mockRoomId)) await fulfillment(of: [expectation]) diff --git a/UnitTests/Sources/InviteUsersViewModelTests.swift b/UnitTests/Sources/InviteUsersViewModelTests.swift index 7deebb12e5..5e3c463681 100644 --- a/UnitTests/Sources/InviteUsersViewModelTests.swift +++ b/UnitTests/Sources/InviteUsersViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -64,7 +55,7 @@ class InviteUsersScreenViewModelTests: XCTestCase { func testInviteButton() async throws { let mockedMembers: [RoomMemberProxyMock] = [.mockAlice, .mockBob] - setupWithRoomType(roomType: .room(roomProxy: RoomProxyMock(.init(name: "test", members: mockedMembers)))) + setupWithRoomType(roomType: .room(roomProxy: JoinedRoomProxyMock(.init(name: "test", members: mockedMembers)))) let deferredState = deferFulfillment(viewModel.context.$viewState) { state in state.isUserSelected(.mockAlice) diff --git a/UnitTests/Sources/JoinRoomScreenViewModelTests.swift b/UnitTests/Sources/JoinRoomScreenViewModelTests.swift index 3bb191442c..ea2ef31a48 100644 --- a/UnitTests/Sources/JoinRoomScreenViewModelTests.swift +++ b/UnitTests/Sources/JoinRoomScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/KeychainControllerTests.swift b/UnitTests/Sources/KeychainControllerTests.swift index aa3ec23e02..f554f1a3c8 100644 --- a/UnitTests/Sources/KeychainControllerTests.swift +++ b/UnitTests/Sources/KeychainControllerTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @testable import ElementX @@ -39,8 +30,8 @@ class KeychainControllerTests: XCTestCase { deviceId: "deviceId", homeserverUrl: "homeserverUrl", oidcData: "oidcData", - slidingSyncProxy: "https://my.sync.proxy"), - sessionDirectory: .homeDirectory.appending(component: UUID().uuidString), + slidingSyncVersion: .proxy(url: "https://my.sync.proxy")), + sessionDirectories: .init(), passphrase: "passphrase", pusherNotificationClientIdentifier: "pusherClientID") keychain.setRestorationToken(restorationToken, forUsername: username) @@ -58,8 +49,8 @@ class KeychainControllerTests: XCTestCase { deviceId: "deviceId", homeserverUrl: "homeserverUrl", oidcData: "oidcData", - slidingSyncProxy: "https://my.sync.proxy"), - sessionDirectory: .homeDirectory.appending(component: UUID().uuidString), + slidingSyncVersion: .proxy(url: "https://my.sync.proxy")), + sessionDirectories: .init(), passphrase: "passphrase", pusherNotificationClientIdentifier: "pusherClientID") keychain.setRestorationToken(restorationToken, forUsername: username) @@ -83,8 +74,8 @@ class KeychainControllerTests: XCTestCase { deviceId: "deviceId", homeserverUrl: "homeserverUrl", oidcData: "oidcData", - slidingSyncProxy: "https://my.sync.proxy"), - sessionDirectory: .homeDirectory.appending(component: UUID().uuidString), + slidingSyncVersion: .proxy(url: "https://my.sync.proxy")), + sessionDirectories: .init(), passphrase: "passphrase", pusherNotificationClientIdentifier: "pusherClientID") keychain.setRestorationToken(restorationToken, forUsername: "@test\(index):example.com") @@ -107,8 +98,8 @@ class KeychainControllerTests: XCTestCase { deviceId: "deviceId", homeserverUrl: "homeserverUrl", oidcData: "oidcData", - slidingSyncProxy: "https://my.sync.proxy"), - sessionDirectory: .homeDirectory.appending(component: UUID().uuidString), + slidingSyncVersion: .proxy(url: "https://my.sync.proxy")), + sessionDirectories: .init(), passphrase: "passphrase", pusherNotificationClientIdentifier: "pusherClientID") keychain.setRestorationToken(restorationToken, forUsername: "@test\(index):example.com") @@ -139,8 +130,8 @@ class KeychainControllerTests: XCTestCase { deviceId: "deviceId", homeserverUrl: "homeserverUrl", oidcData: "oidcData", - slidingSyncProxy: nil), - sessionDirectory: .homeDirectory.appending(component: UUID().uuidString), + slidingSyncVersion: .native), + sessionDirectories: .init(), passphrase: "passphrase", pusherNotificationClientIdentifier: "pusherClientID") keychain.setRestorationToken(restorationToken, forUsername: username) diff --git a/UnitTests/Sources/LayoutTests/CollapsibleFlowLayoutTests.swift b/UnitTests/Sources/LayoutTests/CollapsibleFlowLayoutTests.swift index 0fadfe1cda..4d696cac19 100644 --- a/UnitTests/Sources/LayoutTests/CollapsibleFlowLayoutTests.swift +++ b/UnitTests/Sources/LayoutTests/CollapsibleFlowLayoutTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @testable import ElementX diff --git a/UnitTests/Sources/LayoutTests/LayoutMocks.swift b/UnitTests/Sources/LayoutTests/LayoutMocks.swift index 5e93b6220b..67f0b2f416 100644 --- a/UnitTests/Sources/LayoutTests/LayoutMocks.swift +++ b/UnitTests/Sources/LayoutTests/LayoutMocks.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @testable import ElementX diff --git a/UnitTests/Sources/LegalInformationScreenViewModelTests.swift b/UnitTests/Sources/LegalInformationScreenViewModelTests.swift index ef039e5ac4..544859b630 100644 --- a/UnitTests/Sources/LegalInformationScreenViewModelTests.swift +++ b/UnitTests/Sources/LegalInformationScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/LocalizationTests.swift b/UnitTests/Sources/LocalizationTests.swift index 95a1cd820d..e40d30e175 100644 --- a/UnitTests/Sources/LocalizationTests.swift +++ b/UnitTests/Sources/LocalizationTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @testable import ElementX diff --git a/UnitTests/Sources/LoggingTests.swift b/UnitTests/Sources/LoggingTests.swift index 03c503ee3b..56d34ed35c 100644 --- a/UnitTests/Sources/LoggingTests.swift +++ b/UnitTests/Sources/LoggingTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @testable import ElementX diff --git a/UnitTests/Sources/LoginViewModelTests.swift b/UnitTests/Sources/LoginViewModelTests.swift index 113e60edf5..ba02c88a92 100644 --- a/UnitTests/Sources/LoginViewModelTests.swift +++ b/UnitTests/Sources/LoginViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/MapTilerURLBuildersTests.swift b/UnitTests/Sources/MapTilerURLBuildersTests.swift index f7bc0d0da4..7fa84d6ff0 100644 --- a/UnitTests/Sources/MapTilerURLBuildersTests.swift +++ b/UnitTests/Sources/MapTilerURLBuildersTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import CoreLocation diff --git a/UnitTests/Sources/MatrixEntityRegexTests.swift b/UnitTests/Sources/MatrixEntityRegexTests.swift index 175dcd073d..64eed480a4 100644 --- a/UnitTests/Sources/MatrixEntityRegexTests.swift +++ b/UnitTests/Sources/MatrixEntityRegexTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/UnitTests/Sources/MediaPlayerProviderTests.swift b/UnitTests/Sources/MediaPlayerProviderTests.swift index a93d550255..a9fcca9a6a 100644 --- a/UnitTests/Sources/MediaPlayerProviderTests.swift +++ b/UnitTests/Sources/MediaPlayerProviderTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -73,7 +64,7 @@ class MediaPlayerProviderTests: XCTestCase { // By default, there should be no player state XCTAssertNil(mediaPlayerProvider.playerState(for: audioPlayerStateId)) - let audioPlayerState = AudioPlayerState(id: audioPlayerStateId, duration: 10.0) + let audioPlayerState = AudioPlayerState(id: audioPlayerStateId, title: "", duration: 10.0) mediaPlayerProvider.register(audioPlayerState: audioPlayerState) XCTAssertEqual(audioPlayerState, mediaPlayerProvider.playerState(for: audioPlayerStateId)) @@ -85,7 +76,7 @@ class MediaPlayerProviderTests: XCTestCase { let audioPlayer = AudioPlayerMock() audioPlayer.actions = PassthroughSubject().eraseToAnyPublisher() - let audioPlayerStates = Array(repeating: AudioPlayerState(id: .timelineItemIdentifier(.random), duration: 0), count: 10) + let audioPlayerStates = Array(repeating: AudioPlayerState(id: .timelineItemIdentifier(.random), title: "", duration: 0), count: 10) for audioPlayerState in audioPlayerStates { mediaPlayerProvider.register(audioPlayerState: audioPlayerState) audioPlayerState.attachAudioPlayer(audioPlayer) @@ -104,7 +95,7 @@ class MediaPlayerProviderTests: XCTestCase { let audioPlayer = AudioPlayerMock() audioPlayer.actions = PassthroughSubject().eraseToAnyPublisher() - let audioPlayerStates = Array(repeating: AudioPlayerState(id: .timelineItemIdentifier(.random), duration: 0), count: 10) + let audioPlayerStates = Array(repeating: AudioPlayerState(id: .timelineItemIdentifier(.random), title: "", duration: 0), count: 10) for audioPlayerState in audioPlayerStates { mediaPlayerProvider.register(audioPlayerState: audioPlayerState) audioPlayerState.attachAudioPlayer(audioPlayer) diff --git a/UnitTests/Sources/MediaProvider/MediaLoaderTests.swift b/UnitTests/Sources/MediaProvider/MediaLoaderTests.swift index c4b80f1f79..09d024d381 100644 --- a/UnitTests/Sources/MediaProvider/MediaLoaderTests.swift +++ b/UnitTests/Sources/MediaProvider/MediaLoaderTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @testable import ElementX diff --git a/UnitTests/Sources/MediaProvider/MediaProviderTests.swift b/UnitTests/Sources/MediaProvider/MediaProviderTests.swift index fd45c28743..c33640482f 100644 --- a/UnitTests/Sources/MediaProvider/MediaProviderTests.swift +++ b/UnitTests/Sources/MediaProvider/MediaProviderTests.swift @@ -1,34 +1,75 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @testable import ElementX + +import Combine import Kingfisher import XCTest @MainActor final class MediaProviderTests: XCTestCase { - private let mediaLoader = MockMediaLoader() + private var mediaLoader: MediaLoaderMock! private var imageCache: MockImageCache! + private var networkMonitor: NetworkMonitorMock! var mediaProvider: MediaProvider! override func setUp() { + mediaLoader = MediaLoaderMock() imageCache = MockImageCache(name: "Test") + networkMonitor = NetworkMonitorMock() + mediaProvider = MediaProvider(mediaLoader: mediaLoader, - imageCache: imageCache) + imageCache: imageCache, + networkMonitor: networkMonitor) + } + + func testLoadingRetriedOnReconnection() async throws { + let testImage = try loadTestImage() + guard let pngData = testImage.pngData() else { + XCTFail("Test image should contain valid .png data") + return + } + + let loadTask = mediaProvider.loadImageRetryingOnReconnection(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg")) + + let connectivitySubject = CurrentValueSubject(.unreachable) + + mediaLoader.loadMediaContentForSourceClosure = { _ in + switch connectivitySubject.value { + case .unreachable: + connectivitySubject.send(.reachable) + throw MediaProviderTestsError.error + case .reachable: + return pngData + } + } + + networkMonitor.underlyingReachabilityPublisher = connectivitySubject.asCurrentValuePublisher() + + let result = try? await loadTask.value + + XCTAssertNotNil(result) + XCTAssertEqual(mediaLoader.loadMediaContentForSourceCallsCount, 2) + } + + func testLoadingRetriedOnReconnectionCancelsAfterSecondFailure() async throws { + let loadTask = mediaProvider.loadImageRetryingOnReconnection(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg")) + + let connectivitySubject = CurrentValueSubject(.reachable) + + mediaLoader.loadMediaContentForSourceThrowableError = MediaProviderTestsError.error + + networkMonitor.underlyingReachabilityPublisher = connectivitySubject.asCurrentValuePublisher() + + let result = try? await loadTask.value + + XCTAssertNil(result) } func test_whenImageFromSourceWithSourceNil_nilReturned() throws { @@ -78,7 +119,9 @@ final class MediaProviderTests: XCTestCase { func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFails_imageThumbnailIsLoaded() async throws { let avatarSize = AvatarSize.room(on: .timeline) let expectedImage = try loadTestImage() - mediaLoader.mediaThumbnailData = expectedImage.pngData() + + mediaLoader.loadMediaThumbnailForSourceWidthHeightReturnValue = expectedImage.pngData() + let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg"), size: avatarSize.scaledSize) switch result { @@ -94,7 +137,9 @@ final class MediaProviderTests: XCTestCase { let url = URL.picturesDirectory let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}" let expectedImage = try loadTestImage() - mediaLoader.mediaThumbnailData = expectedImage.pngData() + + mediaLoader.loadMediaThumbnailForSourceWidthHeightReturnValue = expectedImage.pngData() + _ = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"), size: avatarSize.scaledSize) let storedImage = try XCTUnwrap(imageCache.storedImages[key]) @@ -103,7 +148,9 @@ final class MediaProviderTests: XCTestCase { func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndNoAvatarSize_imageContentIsLoaded() async throws { let expectedImage = try loadTestImage() - mediaLoader.mediaContentData = expectedImage.pngData() + + mediaLoader.loadMediaContentForSourceReturnValue = expectedImage.pngData() + let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg"), size: nil) switch result { @@ -115,6 +162,8 @@ 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"), size: AvatarSize.room(on: .timeline).scaledSize) switch result { @@ -126,6 +175,8 @@ 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"), size: nil) switch result { @@ -137,7 +188,8 @@ final class MediaProviderTests: XCTestCase { } func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndImageThumbnailIsLoadedWithCorruptedData_errorIsThrown() async throws { - mediaLoader.mediaThumbnailData = Data() + mediaLoader.loadMediaThumbnailForSourceWidthHeightReturnValue = Data() + let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg"), size: AvatarSize.room(on: .timeline).scaledSize) switch result { @@ -148,30 +200,15 @@ final class MediaProviderTests: XCTestCase { } } - func test_whenLoadFileFromSourceAndFileFromSourceExists_urlIsReturned() async throws { - let expectedURL = URL(filePath: "/some/file/path") - let expectedResult: Result = .success(.unmanaged(url: expectedURL)) - mediaLoader.mediaFileURL = expectedURL - let result = await mediaProvider.loadFileFromSource(MediaSourceProxy(url: "test/test1", mimeType: "video/mp4")) - XCTAssertEqual(result, expectedResult) - } - - func test_whenLoadFileFromSourceAndNoFileFromSourceExistsAndLoadContentSourceFails_failureIsReturned() async throws { - let expectedResult: Result = .failure(.failedRetrievingFile) - mediaLoader.mediaFileURL = nil - let result = await mediaProvider.loadFileFromSource(MediaSourceProxy(url: "test/test1", mimeType: "video/mp4")) - XCTAssertEqual(result, expectedResult) - } - private func loadTestImage() throws -> UIImage { guard let path = Bundle(for: Self.self).path(forResource: "test_image", ofType: "png"), let image = UIImage(contentsOfFile: path) else { - throw MediaProviderTestsError.screenshotNotFound + throw MediaProviderTestsError.error } return image } } -enum MediaProviderTestsError: Error { - case screenshotNotFound +private enum MediaProviderTestsError: Error { + case error } diff --git a/UnitTests/Sources/MediaProvider/MockImageCache.swift b/UnitTests/Sources/MediaProvider/MockImageCache.swift index 0fd9968d9b..4e49317e65 100644 --- a/UnitTests/Sources/MediaProvider/MockImageCache.swift +++ b/UnitTests/Sources/MediaProvider/MockImageCache.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @testable import ElementX import Kingfisher diff --git a/UnitTests/Sources/MediaProvider/MockMediaLoader.swift b/UnitTests/Sources/MediaProvider/MockMediaLoader.swift deleted file mode 100644 index a2270f88e8..0000000000 --- a/UnitTests/Sources/MediaProvider/MockMediaLoader.swift +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -@testable import ElementX -import Foundation - -enum MockMediaLoaderError: Error { - case someError -} - -class MockMediaLoader: MediaLoaderProtocol { - var mediaContentData: Data? - var mediaThumbnailData: Data? - var mediaFileURL: URL? - - func loadMediaContentForSource(_ source: ElementX.MediaSourceProxy) async throws -> Data { - if let mediaContentData { - return mediaContentData - } else { - throw MockMediaLoaderError.someError - } - } - - func loadMediaThumbnailForSource(_ source: ElementX.MediaSourceProxy, width: UInt, height: UInt) async throws -> Data { - if let mediaThumbnailData { - return mediaThumbnailData - } else { - throw MockMediaLoaderError.someError - } - } - - func loadMediaFileForSource(_ source: MediaSourceProxy, body: String?) async throws -> MediaFileHandleProxy { - if let mediaFileURL { - return .unmanaged(url: mediaFileURL) - } else { - throw MockMediaLoaderError.someError - } - } -} diff --git a/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift b/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift index f48ce16dda..880f27acbb 100644 --- a/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift +++ b/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/MediaUploadingPreprocessorTests.swift b/UnitTests/Sources/MediaUploadingPreprocessorTests.swift index c64a603fb2..e33bc64b7a 100644 --- a/UnitTests/Sources/MediaUploadingPreprocessorTests.swift +++ b/UnitTests/Sources/MediaUploadingPreprocessorTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest @@ -37,7 +28,7 @@ final class MediaUploadingPreprocessorTests: XCTestCase { XCTAssertEqual(audioURL.lastPathComponent, "test_audio.mp3") XCTAssertEqual(audioInfo.mimetype, "audio/mpeg") - XCTAssertEqual(audioInfo.duration ?? 0, 27252, accuracy: 100) + XCTAssertEqual(audioInfo.duration ?? 0, 27, accuracy: 100) XCTAssertEqual(audioInfo.size ?? 0, 764_176, accuracy: 100) } @@ -72,11 +63,11 @@ final class MediaUploadingPreprocessorTests: XCTestCase { XCTAssertEqual(videoInfo.size ?? 0, 1_431_959, accuracy: 100) XCTAssertEqual(videoInfo.width, 1280) XCTAssertEqual(videoInfo.height, 720) - XCTAssertEqual(videoInfo.duration ?? 0, 30483, accuracy: 100) + XCTAssertEqual(videoInfo.duration ?? 0, 30, accuracy: 100) XCTAssertNotNil(videoInfo.thumbnailInfo) XCTAssertEqual(videoInfo.thumbnailInfo?.mimetype, "image/jpeg") - XCTAssertEqual(videoInfo.thumbnailInfo?.size ?? 0, 33949, accuracy: 100) + XCTAssertEqual(videoInfo.thumbnailInfo?.size ?? 0, 34206, accuracy: 100) XCTAssertEqual(videoInfo.thumbnailInfo?.width, 800) XCTAssertEqual(videoInfo.thumbnailInfo?.height, 450) } @@ -108,15 +99,15 @@ final class MediaUploadingPreprocessorTests: XCTestCase { // Check resulting video info XCTAssertEqual(videoInfo.mimetype, "video/mp4") - XCTAssertEqual(videoInfo.blurhash, "K7C$_zt70LKQMx^+~B9GIU") + XCTAssertEqual(videoInfo.blurhash, "K7C$_zs;0LKQMx^+~B9GIU") XCTAssertEqual(videoInfo.size ?? 0, 9_775_822, accuracy: 100) XCTAssertEqual(videoInfo.width, 1080) XCTAssertEqual(videoInfo.height, 1920) - XCTAssertEqual(videoInfo.duration ?? 0, 21000, accuracy: 100) + XCTAssertEqual(videoInfo.duration ?? 0, 21, accuracy: 100) XCTAssertNotNil(videoInfo.thumbnailInfo) XCTAssertEqual(videoInfo.thumbnailInfo?.mimetype, "image/jpeg") - XCTAssertEqual(videoInfo.thumbnailInfo?.size ?? 0, 82854, accuracy: 100) + XCTAssertEqual(videoInfo.thumbnailInfo?.size ?? 0, 83220, accuracy: 100) XCTAssertEqual(videoInfo.thumbnailInfo?.width, 337) XCTAssertEqual(videoInfo.thumbnailInfo?.height, 600) } diff --git a/UnitTests/Sources/MessageForwardingScreenViewModelTests.swift b/UnitTests/Sources/MessageForwardingScreenViewModelTests.swift index dccf8c3c80..292d85d1f1 100644 --- a/UnitTests/Sources/MessageForwardingScreenViewModelTests.swift +++ b/UnitTests/Sources/MessageForwardingScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -32,7 +23,7 @@ class MessageForwardingScreenViewModelTests: XCTestCase { cancellables.removeAll() let clientProxy = ClientProxyMock(.init()) - clientProxy.roomForIdentifierClosure = { RoomProxyMock(.init(id: $0)) } + clientProxy.roomForIdentifierClosure = { .joined(JoinedRoomProxyMock(.init(id: $0))) } viewModel = MessageForwardingScreenViewModel(forwardingItem: forwardingItem, clientProxy: clientProxy, diff --git a/UnitTests/Sources/NavigationRootCoordinatorTests.swift b/UnitTests/Sources/NavigationRootCoordinatorTests.swift index 83a8c42a00..3c11026684 100644 --- a/UnitTests/Sources/NavigationRootCoordinatorTests.swift +++ b/UnitTests/Sources/NavigationRootCoordinatorTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest @@ -40,6 +31,22 @@ class NavigationRootCoordinatorTests: XCTestCase { assertCoordinatorsEqual(secondRootCoordinator, navigationRootCoordinator.rootCoordinator) } + func testOverlay() { + let rootCoordinator = SomeTestCoordinator() + navigationRootCoordinator.setRootCoordinator(rootCoordinator) + + let overlayCoordinator = SomeTestCoordinator() + navigationRootCoordinator.setOverlayCoordinator(overlayCoordinator) + + assertCoordinatorsEqual(rootCoordinator, navigationRootCoordinator.rootCoordinator) + assertCoordinatorsEqual(overlayCoordinator, navigationRootCoordinator.overlayCoordinator) + + navigationRootCoordinator.setOverlayCoordinator(nil) + + assertCoordinatorsEqual(rootCoordinator, navigationRootCoordinator.rootCoordinator) + XCTAssertNil(navigationRootCoordinator.overlayCoordinator) + } + func testReplacementDismissalCallbacks() { XCTAssertNil(navigationRootCoordinator.rootCoordinator) @@ -54,6 +61,18 @@ class NavigationRootCoordinatorTests: XCTestCase { waitForExpectations(timeout: 1.0) } + func testOverlayDismissalCallback() { + let overlayCoordinator = SomeTestCoordinator() + + let expectation = expectation(description: "Wait for callback") + navigationRootCoordinator.setOverlayCoordinator(overlayCoordinator) { + expectation.fulfill() + } + + navigationRootCoordinator.setOverlayCoordinator(nil) + waitForExpectations(timeout: 1.0) + } + // MARK: - Private private func assertCoordinatorsEqual(_ lhs: CoordinatorProtocol?, _ rhs: CoordinatorProtocol?) { diff --git a/UnitTests/Sources/NavigationSplitCoordinatorTests.swift b/UnitTests/Sources/NavigationSplitCoordinatorTests.swift index cc5b7181e0..845405dd22 100644 --- a/UnitTests/Sources/NavigationSplitCoordinatorTests.swift +++ b/UnitTests/Sources/NavigationSplitCoordinatorTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest @@ -99,6 +90,52 @@ class NavigationSplitCoordinatorTests: XCTestCase { assertCoordinatorsEqual(someOtherSheetCoordinator, navigationSplitCoordinator.sheetCoordinator) } + func testFullScreenCover() { + let sidebarCoordinator = SomeTestCoordinator() + navigationSplitCoordinator.setSidebarCoordinator(sidebarCoordinator) + let detailCoordinator = SomeTestCoordinator() + navigationSplitCoordinator.setDetailCoordinator(detailCoordinator) + + let fullScreenCoordinator = SomeTestCoordinator() + navigationSplitCoordinator.setFullScreenCoverCoordinator(fullScreenCoordinator) + + assertCoordinatorsEqual(sidebarCoordinator, navigationSplitCoordinator.sidebarCoordinator) + assertCoordinatorsEqual(detailCoordinator, navigationSplitCoordinator.detailCoordinator) + assertCoordinatorsEqual(fullScreenCoordinator, navigationSplitCoordinator.fullScreenCoverCoordinator) + + navigationSplitCoordinator.setFullScreenCoverCoordinator(nil) + + assertCoordinatorsEqual(sidebarCoordinator, navigationSplitCoordinator.sidebarCoordinator) + assertCoordinatorsEqual(detailCoordinator, navigationSplitCoordinator.detailCoordinator) + XCTAssertNil(navigationSplitCoordinator.fullScreenCoverCoordinator) + } + + func testOverlay() { + let sidebarCoordinator = SomeTestCoordinator() + navigationSplitCoordinator.setSidebarCoordinator(sidebarCoordinator) + let detailCoordinator = SomeTestCoordinator() + navigationSplitCoordinator.setDetailCoordinator(detailCoordinator) + + let overlayCoordinator = SomeTestCoordinator() + navigationSplitCoordinator.setOverlayCoordinator(overlayCoordinator) + + assertCoordinatorsEqual(sidebarCoordinator, navigationSplitCoordinator.sidebarCoordinator) + assertCoordinatorsEqual(detailCoordinator, navigationSplitCoordinator.detailCoordinator) + assertCoordinatorsEqual(overlayCoordinator, navigationSplitCoordinator.overlayCoordinator) + + // The coordinator should still be retained when changing the presentation mode. + navigationSplitCoordinator.setOverlayPresentationMode(.minimized) + assertCoordinatorsEqual(overlayCoordinator, navigationSplitCoordinator.overlayCoordinator) + navigationSplitCoordinator.setOverlayPresentationMode(.fullScreen) + assertCoordinatorsEqual(overlayCoordinator, navigationSplitCoordinator.overlayCoordinator) + + navigationSplitCoordinator.setOverlayCoordinator(nil) + + assertCoordinatorsEqual(sidebarCoordinator, navigationSplitCoordinator.sidebarCoordinator) + assertCoordinatorsEqual(detailCoordinator, navigationSplitCoordinator.detailCoordinator) + XCTAssertNil(navigationSplitCoordinator.overlayCoordinator) + } + func testSidebarReplacementCallbacks() { let sidebarCoordinator = SomeTestCoordinator() @@ -135,6 +172,43 @@ class NavigationSplitCoordinatorTests: XCTestCase { waitForExpectations(timeout: 1.0) } + func testFullScreenCoverDismissalCallback() { + let fullScreenCoordinator = SomeTestCoordinator() + + let expectation = expectation(description: "Wait for callback") + navigationSplitCoordinator.setFullScreenCoverCoordinator(fullScreenCoordinator) { + expectation.fulfill() + } + + navigationSplitCoordinator.setFullScreenCoverCoordinator(nil) + waitForExpectations(timeout: 1.0) + } + + func testOverlayDismissalCallback() { + let overlayCoordinator = SomeTestCoordinator() + + let expectation = expectation(description: "Wait for callback") + navigationSplitCoordinator.setOverlayCoordinator(overlayCoordinator) { + expectation.fulfill() + } + + navigationSplitCoordinator.setOverlayCoordinator(nil) + waitForExpectations(timeout: 1.0) + } + + func testOverlayDismissalCallbackWhenChangingMode() { + let overlayCoordinator = SomeTestCoordinator() + + let expectation = expectation(description: "Wait for callback") + expectation.isInverted = true + navigationSplitCoordinator.setOverlayCoordinator(overlayCoordinator) { + expectation.fulfill() + } + + navigationSplitCoordinator.setOverlayPresentationMode(.minimized) + waitForExpectations(timeout: 1.0) + } + func testEmbeddedStackPresentsSheetThroughSplit() { let sidebarNavigationStackCoordinator = NavigationStackCoordinator(navigationSplitCoordinator: navigationSplitCoordinator) sidebarNavigationStackCoordinator.setRootCoordinator(SomeTestCoordinator()) diff --git a/UnitTests/Sources/NavigationStackCoordinatorTests.swift b/UnitTests/Sources/NavigationStackCoordinatorTests.swift index 21996d5003..854e4e5cc0 100644 --- a/UnitTests/Sources/NavigationStackCoordinatorTests.swift +++ b/UnitTests/Sources/NavigationStackCoordinatorTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/NotificationManager/MockCoder.swift b/UnitTests/Sources/NotificationManager/MockCoder.swift index 595cb78162..a10a975971 100644 --- a/UnitTests/Sources/NotificationManager/MockCoder.swift +++ b/UnitTests/Sources/NotificationManager/MockCoder.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/UnitTests/Sources/NotificationManager/NotificationManagerTests.swift b/UnitTests/Sources/NotificationManager/NotificationManagerTests.swift index 81bb9a37fa..2755b65e41 100644 --- a/UnitTests/Sources/NotificationManager/NotificationManagerTests.swift +++ b/UnitTests/Sources/NotificationManager/NotificationManagerTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/UnitTests/Sources/NotificationManager/UNNotification+Creator.swift b/UnitTests/Sources/NotificationManager/UNNotification+Creator.swift index 90e841ecb0..78c615ad44 100644 --- a/UnitTests/Sources/NotificationManager/UNNotification+Creator.swift +++ b/UnitTests/Sources/NotificationManager/UNNotification+Creator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/UnitTests/Sources/NotificationManager/UNTextInputNotificationResponse+Creator.swift b/UnitTests/Sources/NotificationManager/UNTextInputNotificationResponse+Creator.swift index 8a290db0fb..c757db01f9 100644 --- a/UnitTests/Sources/NotificationManager/UNTextInputNotificationResponse+Creator.swift +++ b/UnitTests/Sources/NotificationManager/UNTextInputNotificationResponse+Creator.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import UserNotifications diff --git a/UnitTests/Sources/NotificationSettingsEditScreenViewModelTests.swift b/UnitTests/Sources/NotificationSettingsEditScreenViewModelTests.swift index 91da060ebf..00c3d0bf86 100644 --- a/UnitTests/Sources/NotificationSettingsEditScreenViewModelTests.swift +++ b/UnitTests/Sources/NotificationSettingsEditScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import MatrixRustSDK diff --git a/UnitTests/Sources/NotificationSettingsScreenViewModelTests.swift b/UnitTests/Sources/NotificationSettingsScreenViewModelTests.swift index bc3eeb7089..4ad7b6bccb 100644 --- a/UnitTests/Sources/NotificationSettingsScreenViewModelTests.swift +++ b/UnitTests/Sources/NotificationSettingsScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import MatrixRustSDK diff --git a/UnitTests/Sources/PermalinkTests.swift b/UnitTests/Sources/PermalinkTests.swift index 554d4f0ee7..4ea52bb71d 100644 --- a/UnitTests/Sources/PermalinkTests.swift +++ b/UnitTests/Sources/PermalinkTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @testable import ElementX diff --git a/UnitTests/Sources/PillContextTests.swift b/UnitTests/Sources/PillContextTests.swift index 3ddbd4f78a..12b926b481 100644 --- a/UnitTests/Sources/PillContextTests.swift +++ b/UnitTests/Sources/PillContextTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -23,19 +14,19 @@ import XCTest class PillContextTests: XCTestCase { func testUser() async throws { let id = "@test:matrix.org" - let proxyMock = RoomProxyMock(.init(name: "Test")) + let proxyMock = JoinedRoomProxyMock(.init(name: "Test")) let subject = CurrentValueSubject<[RoomMemberProxyProtocol], Never>([]) proxyMock.membersPublisher = subject.asCurrentValuePublisher() - let mock = RoomScreenViewModel(roomProxy: proxyMock, - timelineController: MockRoomTimelineController(), - mediaProvider: MockMediaProvider(), - mediaPlayerProvider: MediaPlayerProviderMock(), - voiceMessageMediaManager: VoiceMessageMediaManagerMock(), - userIndicatorController: ServiceLocator.shared.userIndicatorController, - appMediator: AppMediatorMock.default, - appSettings: ServiceLocator.shared.settings, - analyticsService: ServiceLocator.shared.analytics) - let context = PillContext(roomContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body))) + let mock = TimelineViewModel(roomProxy: proxyMock, + timelineController: MockRoomTimelineController(), + mediaProvider: MockMediaProvider(), + mediaPlayerProvider: MediaPlayerProviderMock(), + voiceMessageMediaManager: VoiceMessageMediaManagerMock(), + userIndicatorController: ServiceLocator.shared.userIndicatorController, + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) + let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body))) XCTAssertFalse(context.viewState.isOwnMention) XCTAssertEqual(context.viewState.displayText, id) @@ -51,19 +42,19 @@ class PillContextTests: XCTestCase { func testOwnUser() async throws { let id = "@test:matrix.org" - let proxyMock = RoomProxyMock(.init(name: "Test", ownUserID: id)) + let proxyMock = JoinedRoomProxyMock(.init(name: "Test", ownUserID: id)) let subject = CurrentValueSubject<[RoomMemberProxyProtocol], Never>([]) proxyMock.membersPublisher = subject.asCurrentValuePublisher() - let mock = RoomScreenViewModel(roomProxy: proxyMock, - timelineController: MockRoomTimelineController(), - mediaProvider: MockMediaProvider(), - mediaPlayerProvider: MediaPlayerProviderMock(), - voiceMessageMediaManager: VoiceMessageMediaManagerMock(), - userIndicatorController: ServiceLocator.shared.userIndicatorController, - appMediator: AppMediatorMock.default, - appSettings: ServiceLocator.shared.settings, - analyticsService: ServiceLocator.shared.analytics) - let context = PillContext(roomContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body))) + let mock = TimelineViewModel(roomProxy: proxyMock, + timelineController: MockRoomTimelineController(), + mediaProvider: MockMediaProvider(), + mediaPlayerProvider: MediaPlayerProviderMock(), + voiceMessageMediaManager: VoiceMessageMediaManagerMock(), + userIndicatorController: ServiceLocator.shared.userIndicatorController, + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) + let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body))) XCTAssertTrue(context.viewState.isOwnMention) } @@ -72,19 +63,19 @@ class PillContextTests: XCTestCase { let avatarURL = URL(string: "https://matrix.jpg") let id = "test_room" let displayName = "Test" - let proxyMock = RoomProxyMock(.init(id: id, name: displayName, avatarURL: avatarURL)) + let proxyMock = JoinedRoomProxyMock(.init(id: id, name: displayName, avatarURL: avatarURL)) let mockController = MockRoomTimelineController() mockController.roomProxy = proxyMock - let mock = RoomScreenViewModel(roomProxy: proxyMock, - timelineController: mockController, - mediaProvider: MockMediaProvider(), - mediaPlayerProvider: MediaPlayerProviderMock(), - voiceMessageMediaManager: VoiceMessageMediaManagerMock(), - userIndicatorController: ServiceLocator.shared.userIndicatorController, - appMediator: AppMediatorMock.default, - appSettings: ServiceLocator.shared.settings, - analyticsService: ServiceLocator.shared.analytics) - let context = PillContext(roomContext: mock.context, data: PillTextAttachmentData(type: .allUsers, font: .preferredFont(forTextStyle: .body))) + let mock = TimelineViewModel(roomProxy: proxyMock, + timelineController: mockController, + mediaProvider: MockMediaProvider(), + mediaPlayerProvider: MediaPlayerProviderMock(), + voiceMessageMediaManager: VoiceMessageMediaManagerMock(), + userIndicatorController: ServiceLocator.shared.userIndicatorController, + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) + let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .allUsers, font: .preferredFont(forTextStyle: .body))) XCTAssertTrue(context.viewState.isOwnMention) XCTAssertEqual(context.viewState.displayText, PillConstants.atRoom) diff --git a/UnitTests/Sources/PinnedEventsBannerStateTests.swift b/UnitTests/Sources/PinnedEventsBannerStateTests.swift index 9e35c5664f..52f14b4589 100644 --- a/UnitTests/Sources/PinnedEventsBannerStateTests.swift +++ b/UnitTests/Sources/PinnedEventsBannerStateTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest @@ -37,9 +28,9 @@ class PinnedEventsBannerStateTests: XCTestCase { XCTAssertTrue(state.isLoading) XCTAssertFalse(state.isEmpty) - XCTAssertNil(state.selectedPinEventID) + XCTAssertNil(state.selectedPinnedEventID) XCTAssertEqual(state.displayedMessage.string, L10n.screenRoomPinnedBannerLoadingDescription) - XCTAssertEqual(state.selectedPinIndex, 4) + XCTAssertEqual(state.selectedPinnedIndex, 4) XCTAssertEqual(state.count, 5) XCTAssertEqual(state.bannerIndicatorDescription.string, L10n.screenRoomPinnedBannerIndicatorDescription(L10n.screenRoomPinnedBannerIndicator(5, 5))) } @@ -48,42 +39,42 @@ class PinnedEventsBannerStateTests: XCTestCase { var state = PinnedEventsBannerState.loading(numbersOfEvents: 2) XCTAssertTrue(state.isLoading) state.setPinnedEventContents(["1": "test1", "2": "test2"]) - XCTAssertEqual(state, .loaded(state: .init(pinnedEventContents: ["1": "test1", "2": "test2"], selectedPinEventID: "2"))) + XCTAssertEqual(state, .loaded(state: .init(pinnedEventContents: ["1": "test1", "2": "test2"], selectedPinnedEventID: "2"))) XCTAssertFalse(state.isLoading) } func testLoaded() { - let state = PinnedEventsBannerState.loaded(state: .init(pinnedEventContents: ["1": "test1", "2": "test2"], selectedPinEventID: "2")) + let state = PinnedEventsBannerState.loaded(state: .init(pinnedEventContents: ["1": "test1", "2": "test2"], selectedPinnedEventID: "2")) XCTAssertFalse(state.isLoading) XCTAssertFalse(state.isEmpty) - XCTAssertEqual(state.selectedPinEventID, "2") + XCTAssertEqual(state.selectedPinnedEventID, "2") XCTAssertEqual(state.displayedMessage.string, "test2") - XCTAssertEqual(state.selectedPinIndex, 1) + XCTAssertEqual(state.selectedPinnedIndex, 1) XCTAssertEqual(state.count, 2) XCTAssertEqual(state.bannerIndicatorDescription.string, L10n.screenRoomPinnedBannerIndicatorDescription(L10n.screenRoomPinnedBannerIndicator(2, 2))) } func testPreviousPin() { - var state = PinnedEventsBannerState.loaded(state: .init(pinnedEventContents: ["1": "test1", "2": "test2", "3": "test3"], selectedPinEventID: "1")) - XCTAssertEqual(state.selectedPinEventID, "1") - XCTAssertEqual(state.selectedPinIndex, 0) + var state = PinnedEventsBannerState.loaded(state: .init(pinnedEventContents: ["1": "test1", "2": "test2", "3": "test3"], selectedPinnedEventID: "1")) + XCTAssertEqual(state.selectedPinnedEventID, "1") + XCTAssertEqual(state.selectedPinnedIndex, 0) XCTAssertEqual(state.displayedMessage.string, "test1") state.previousPin() - XCTAssertEqual(state.selectedPinEventID, "3") - XCTAssertEqual(state.selectedPinIndex, 2) + XCTAssertEqual(state.selectedPinnedEventID, "3") + XCTAssertEqual(state.selectedPinnedIndex, 2) XCTAssertEqual(state.displayedMessage.string, "test3") state.previousPin() - XCTAssertEqual(state.selectedPinEventID, "2") - XCTAssertEqual(state.selectedPinIndex, 1) + XCTAssertEqual(state.selectedPinnedEventID, "2") + XCTAssertEqual(state.selectedPinnedIndex, 1) XCTAssertEqual(state.displayedMessage.string, "test2") } func testSetContent() { - var state = PinnedEventsBannerState.loaded(state: .init(pinnedEventContents: ["1": "test1", "2": "test2", "3": "test3", "4": "test4"], selectedPinEventID: "2")) - XCTAssertEqual(state.selectedPinEventID, "2") - XCTAssertEqual(state.selectedPinIndex, 1) + var state = PinnedEventsBannerState.loaded(state: .init(pinnedEventContents: ["1": "test1", "2": "test2", "3": "test3", "4": "test4"], selectedPinnedEventID: "2")) + XCTAssertEqual(state.selectedPinnedEventID, "2") + XCTAssertEqual(state.selectedPinnedIndex, 1) XCTAssertEqual(state.displayedMessage.string, "test2") XCTAssertEqual(state.count, 4) XCTAssertFalse(state.isEmpty) @@ -91,8 +82,8 @@ class PinnedEventsBannerStateTests: XCTestCase { // let's remove the selected item state.setPinnedEventContents(["1": "test1", "3": "test3", "4": "test4"]) // new selected item is the new latest - XCTAssertEqual(state.selectedPinEventID, "4") - XCTAssertEqual(state.selectedPinIndex, 2) + XCTAssertEqual(state.selectedPinnedEventID, "4") + XCTAssertEqual(state.selectedPinnedIndex, 2) XCTAssertEqual(state.displayedMessage.string, "test4") XCTAssertEqual(state.count, 3) XCTAssertFalse(state.isEmpty) @@ -100,9 +91,9 @@ class PinnedEventsBannerStateTests: XCTestCase { // let's add a new item at the top state.setPinnedEventContents(["0": "test0", "1": "test1", "3": "test3", "4": "test4"]) // selected item doesn't change - XCTAssertEqual(state.selectedPinEventID, "4") + XCTAssertEqual(state.selectedPinnedEventID, "4") // but the index is updated - XCTAssertEqual(state.selectedPinIndex, 3) + XCTAssertEqual(state.selectedPinnedIndex, 3) XCTAssertEqual(state.displayedMessage.string, "test4") XCTAssertEqual(state.count, 4) XCTAssertFalse(state.isEmpty) @@ -110,9 +101,9 @@ class PinnedEventsBannerStateTests: XCTestCase { // let's add a new item at the bottom state.setPinnedEventContents(["0": "test0", "1": "test1", "3": "test3", "4": "test4", "5": "test5"]) // selected item doesn't change - XCTAssertEqual(state.selectedPinEventID, "4") + XCTAssertEqual(state.selectedPinnedEventID, "4") // and index stays the same - XCTAssertEqual(state.selectedPinIndex, 3) + XCTAssertEqual(state.selectedPinnedIndex, 3) XCTAssertEqual(state.displayedMessage.string, "test4") XCTAssertEqual(state.count, 5) XCTAssertFalse(state.isEmpty) @@ -120,12 +111,12 @@ class PinnedEventsBannerStateTests: XCTestCase { // set to tempty state.setPinnedEventContents([:]) XCTAssertTrue(state.isEmpty) - XCTAssertNil(state.selectedPinEventID) + XCTAssertNil(state.selectedPinnedEventID) // set to one item state.setPinnedEventContents(["6": "test6", "7": "test7"]) - XCTAssertEqual(state.selectedPinEventID, "7") - XCTAssertEqual(state.selectedPinIndex, 1) + XCTAssertEqual(state.selectedPinnedEventID, "7") + XCTAssertEqual(state.selectedPinnedIndex, 1) XCTAssertEqual(state.displayedMessage.string, "test7") XCTAssertEqual(state.count, 2) XCTAssertFalse(state.isEmpty) diff --git a/UnitTests/Sources/PollFormScreenViewModelTests.swift b/UnitTests/Sources/PollFormScreenViewModelTests.swift index 76eff0879d..af92477aca 100644 --- a/UnitTests/Sources/PollFormScreenViewModelTests.swift +++ b/UnitTests/Sources/PollFormScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/QRCodeLoginScreenViewModelTests.swift b/UnitTests/Sources/QRCodeLoginScreenViewModelTests.swift index dd444b86b4..088ccbebfc 100644 --- a/UnitTests/Sources/QRCodeLoginScreenViewModelTests.swift +++ b/UnitTests/Sources/QRCodeLoginScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/UnitTests/Sources/ReportContentViewModelTests.swift b/UnitTests/Sources/ReportContentViewModelTests.swift index ceded0d44b..bda0f8456a 100644 --- a/UnitTests/Sources/ReportContentViewModelTests.swift +++ b/UnitTests/Sources/ReportContentViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @testable import ElementX @@ -25,7 +16,7 @@ class ReportContentScreenViewModelTests: XCTestCase { func testReportContent() async throws { // Given the report content view for some content. - let roomProxy = RoomProxyMock(.init(name: "test")) + let roomProxy = JoinedRoomProxyMock(.init(name: "test")) roomProxy.reportContentReasonReturnValue = .success(()) let clientProxy = ClientProxyMock(.init()) let viewModel = ReportContentScreenViewModel(eventID: eventID, @@ -54,7 +45,7 @@ class ReportContentScreenViewModelTests: XCTestCase { func testReportIgnoringSender() async throws { // Given the report content view for some content. - let roomProxy = RoomProxyMock(.init(name: "test")) + let roomProxy = JoinedRoomProxyMock(.init(name: "test")) roomProxy.reportContentReasonReturnValue = .success(()) let clientProxy = ClientProxyMock(.init()) let viewModel = ReportContentScreenViewModel(eventID: eventID, diff --git a/UnitTests/Sources/ResolveVerifiedUserSendFailureScreenViewModelTests.swift b/UnitTests/Sources/ResolveVerifiedUserSendFailureScreenViewModelTests.swift new file mode 100644 index 0000000000..91fc8e4279 --- /dev/null +++ b/UnitTests/Sources/ResolveVerifiedUserSendFailureScreenViewModelTests.swift @@ -0,0 +1,115 @@ +// +// Copyright 2022 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import XCTest + +@testable import ElementX + +@MainActor +class ResolveVerifiedUserSendFailureScreenViewModelTests: XCTestCase { + let roomProxy = JoinedRoomProxyMock(.init()) + var viewModel: ResolveVerifiedUserSendFailureScreenViewModel! + var context: ResolveVerifiedUserSendFailureScreenViewModel.Context { viewModel.context } + + func testUnsignedDevice() async throws { + // Given a failure where a single user has an unverified device + let userID = "@alice:matrix.org" + viewModel = makeViewModel(with: .hasUnsignedDevice(devices: [userID: ["DEVICE1"]])) + + try await verifyResolving(userIDs: [userID]) + } + + func testMultipleUnsignedDevices() async throws { + // Given a failure where a multiple users have unverified devices. + let userIDs = ["@alice:matrix.org", "@bob:matrix.org", "@charlie:matrix.org"] + let devices = Dictionary(uniqueKeysWithValues: userIDs.map { (key: $0, value: ["DEVICE1, DEVICE2"]) }) + viewModel = makeViewModel(with: .hasUnsignedDevice(devices: devices)) + + try await verifyResolving(userIDs: userIDs, assertStrings: false) + } + + func testChangedIdentity() async throws { + // Given a failure where a single user's identity has changed. + let userID = "@alice:matrix.org" + viewModel = makeViewModel(with: .changedIdentity(users: [userID])) + + try await verifyResolving(userIDs: [userID]) + } + + func testMultipleChangedIdentities() async throws { + // Given a failure where a multiple users have unverified devices. + let userIDs = ["@alice:matrix.org", "@bob:matrix.org", "@charlie:matrix.org"] + viewModel = makeViewModel(with: .changedIdentity(users: userIDs)) + + try await verifyResolving(userIDs: userIDs) + } + + // MARK: Helpers + + private func makeViewModel(with failure: TimelineItemSendFailure.VerifiedUser) -> ResolveVerifiedUserSendFailureScreenViewModel { + ResolveVerifiedUserSendFailureScreenViewModel(failure: failure, + itemID: .random, + roomProxy: roomProxy, + userIndicatorController: UserIndicatorControllerMock()) + } + + private func verifyResolving(userIDs: [String], assertStrings: Bool = true) async throws { + var remainingUserIDs = userIDs + + while remainingUserIDs.count > 1 { + // Verify that the strings are being updated. + if assertStrings { + verifyDisplayName(from: remainingUserIDs) + } + + // When resolving the first failure. + let deferredFailure = deferFailure(viewModel.actionsPublisher, timeout: 1) { $0 == .dismiss } + context.send(viewAction: .resolveAndResend) + + // Then the sheet should remain open for the next failure. + try await deferredFailure.fulfill() + + remainingUserIDs.removeFirst() + } + + // Verify the final string. + if assertStrings { + verifyDisplayName(from: remainingUserIDs) + } + + // When resolving the final failure. + let deferred = deferFulfillment(viewModel.actionsPublisher) { $0 == .dismiss } + context.send(viewAction: .resolveAndResend) + + // Then the sheet should be dismissed. + try await deferred.fulfill() + } + + private func verifyDisplayName(from remainingUserIDs: [String]) { + guard let userID = remainingUserIDs.first else { + XCTFail("There should be a user ID to check.") + return + } + + guard let displayName = roomProxy.membersPublisher.value.first(where: { $0.userID == userID })?.displayName else { + XCTFail("There should be a matching mock user") + return + } + + XCTAssertTrue(context.viewState.title.contains(displayName)) + XCTAssertTrue(context.viewState.subtitle.contains(displayName)) + } +} diff --git a/UnitTests/Sources/RestorationTokenTests.swift b/UnitTests/Sources/RestorationTokenTests.swift new file mode 100644 index 0000000000..404ae04ad3 --- /dev/null +++ b/UnitTests/Sources/RestorationTokenTests.swift @@ -0,0 +1,136 @@ +// +// Copyright 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 +import MatrixRustSDK + +class RestorationTokenTests: XCTestCase { + func testDecodeFromTokenV1() throws { + // Given an encoded restoration token in the original format that only contains a Session from the SDK. + let originalToken = RestorationTokenV1(session: Session(accessToken: "1234", + refreshToken: nil, + userId: "@user:example.com", + deviceId: "D3V1C3", + homeserverUrl: "https://matrix.example.com", + oidcData: nil, + slidingSyncVersion: .proxy(url: "https://sync.example.com"))) + let data = try JSONEncoder().encode(originalToken) + + // When decoding the data to the current restoration token format. + let decodedToken = try JSONDecoder().decode(RestorationToken.self, from: data) + + // Then the output should be a valid token with the expected store directories. + XCTAssertEqual(decodedToken.session, originalToken.session, "The session should not be changed.") + XCTAssertNil(decodedToken.passphrase, "There should not be a passphrase.") + 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"), + "The cache directory should be derived from the session directory but in the caches directory.") + } + + func testDecodeFromTokenV4() throws { + // Given an encoded restoration token in the 4th format that contains a stored session directory. + let sessionDirectoryName = UUID().uuidString + let originalToken = RestorationTokenV4(session: Session(accessToken: "1234", + refreshToken: "5678", + userId: "@user:example.com", + deviceId: "D3V1C3", + homeserverUrl: "https://matrix.example.com", + oidcData: "data-from-mas", + slidingSyncVersion: .proxy(url: "https://sync.example.com")), + sessionDirectory: .sessionsBaseDirectory.appending(component: sessionDirectoryName), + passphrase: "passphrase", + pusherNotificationClientIdentifier: "pusher-identifier") + let data = try JSONEncoder().encode(originalToken) + + // When decoding the data to the current restoration token format. + let decodedToken = try JSONDecoder().decode(RestorationToken.self, from: data) + + // Then the output should be a valid token with the expected store directories. + XCTAssertEqual(decodedToken.session, originalToken.session, "The session should not be changed.") + XCTAssertEqual(decodedToken.passphrase, originalToken.passphrase, "The passphrase should not be changed.") + XCTAssertEqual(decodedToken.pusherNotificationClientIdentifier, originalToken.pusherNotificationClientIdentifier, + "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), + "The cache directory should be derived from the session directory but in the caches directory.") + } + + func testDecodeFromTokenV5() throws { + // Given an encoded restoration token in the 5th format that contains separate directories for session data and caches. + let sessionDirectoryName = UUID().uuidString + let originalToken = RestorationTokenV5(session: Session(accessToken: "1234", + refreshToken: "5678", + userId: "@user:example.com", + deviceId: "D3V1C3", + homeserverUrl: "https://matrix.example.com", + oidcData: "data-from-mas", + slidingSyncVersion: .native), + sessionDirectory: .sessionsBaseDirectory.appending(component: sessionDirectoryName), + cacheDirectory: .cachesBaseDirectory.appending(component: sessionDirectoryName), + passphrase: "passphrase", + pusherNotificationClientIdentifier: "pusher-identifier") + let data = try JSONEncoder().encode(originalToken) + + // When decoding the data. + let decodedToken = try JSONDecoder().decode(RestorationToken.self, from: data) + + // Then the output should be a valid token. + XCTAssertEqual(decodedToken.session, originalToken.session, "The session should not be changed.") + XCTAssertEqual(decodedToken.passphrase, originalToken.passphrase, "The passphrase should not be changed.") + XCTAssertEqual(decodedToken.pusherNotificationClientIdentifier, originalToken.pusherNotificationClientIdentifier, + "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, originalToken.cacheDirectory, + "The cache directory should not be changed.") + } + + func testDecodeFromCurrentToken() throws { + // Given an encoded restoration token in the current format. + let originalToken = RestorationToken(session: Session(accessToken: "1234", + refreshToken: "5678", + userId: "@user:example.com", + deviceId: "D3V1C3", + homeserverUrl: "https://matrix.example.com", + oidcData: "data-from-mas", + slidingSyncVersion: .native), + sessionDirectories: .init(), + passphrase: "passphrase", + pusherNotificationClientIdentifier: "pusher-identifier") + let data = try JSONEncoder().encode(originalToken) + + // When decoding the data. + let decodedToken = try JSONDecoder().decode(RestorationToken.self, from: data) + + // Then the output should be a valid token. + XCTAssertEqual(decodedToken, originalToken, "The token should remain identical.") + } +} + +struct RestorationTokenV1: Equatable, Codable { + let session: MatrixRustSDK.Session +} + +struct RestorationTokenV4: Equatable, Codable { + let session: MatrixRustSDK.Session + let sessionDirectory: URL + let passphrase: String? + let pusherNotificationClientIdentifier: String? +} + +struct RestorationTokenV5: Equatable, Codable { + let session: MatrixRustSDK.Session + let sessionDirectory: URL + let cacheDirectory: URL + let passphrase: String? + let pusherNotificationClientIdentifier: String? +} diff --git a/UnitTests/Sources/RoomChangePermissionsScreenViewModelTests.swift b/UnitTests/Sources/RoomChangePermissionsScreenViewModelTests.swift index 555756bc2b..a7c94232cc 100644 --- a/UnitTests/Sources/RoomChangePermissionsScreenViewModelTests.swift +++ b/UnitTests/Sources/RoomChangePermissionsScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest @@ -20,7 +11,7 @@ import XCTest @MainActor class RoomChangePermissionsScreenViewModelTests: XCTestCase { - var roomProxy: RoomProxyMock! + var roomProxy: JoinedRoomProxyMock! var viewModel: RoomChangePermissionsScreenViewModelProtocol! var context: RoomChangePermissionsScreenViewModelType.Context { @@ -28,7 +19,7 @@ class RoomChangePermissionsScreenViewModelTests: XCTestCase { } override func setUp() { - roomProxy = RoomProxyMock(.init()) + roomProxy = JoinedRoomProxyMock(.init()) viewModel = RoomChangePermissionsScreenViewModel(currentPermissions: .init(powerLevels: .mock), group: .roomDetails, roomProxy: roomProxy, diff --git a/UnitTests/Sources/RoomChangeRolesScreenViewModelTests.swift b/UnitTests/Sources/RoomChangeRolesScreenViewModelTests.swift index ea3a922b0c..427ff39e90 100644 --- a/UnitTests/Sources/RoomChangeRolesScreenViewModelTests.swift +++ b/UnitTests/Sources/RoomChangeRolesScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest @@ -21,7 +12,7 @@ import XCTest @MainActor class RoomChangeRolesScreenViewModelTests: XCTestCase { var viewModel: RoomChangeRolesScreenViewModelProtocol! - var roomProxy: RoomProxyMock! + var roomProxy: JoinedRoomProxyMock! var context: RoomChangeRolesScreenViewModelType.Context { viewModel.context @@ -202,7 +193,7 @@ class RoomChangeRolesScreenViewModelTests: XCTestCase { } private func setupViewModel(mode: RoomMemberDetails.Role) { - roomProxy = RoomProxyMock(.init(members: .allMembersAsAdmin)) + roomProxy = JoinedRoomProxyMock(.init(members: .allMembersAsAdmin)) viewModel = RoomChangeRolesScreenViewModel(mode: mode, roomProxy: roomProxy, mediaProvider: MockMediaProvider(), diff --git a/UnitTests/Sources/RoomDetailsEditScreenViewModelTests.swift b/UnitTests/Sources/RoomDetailsEditScreenViewModelTests.swift index 9a2a3a6567..ad79d87fa2 100644 --- a/UnitTests/Sources/RoomDetailsEditScreenViewModelTests.swift +++ b/UnitTests/Sources/RoomDetailsEditScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import MatrixRustSDK @@ -117,9 +108,9 @@ class RoomDetailsEditScreenViewModelTests: XCTestCase { // MARK: - Private - private func setupViewModel(roomProxyConfiguration: RoomProxyMockConfiguration) { + private func setupViewModel(roomProxyConfiguration: JoinedRoomProxyMockConfiguration) { userIndicatorController = UserIndicatorControllerMock.default - viewModel = .init(roomProxy: RoomProxyMock(roomProxyConfiguration), + viewModel = .init(roomProxy: JoinedRoomProxyMock(roomProxyConfiguration), mediaProvider: MockMediaProvider(), userIndicatorController: userIndicatorController) } diff --git a/UnitTests/Sources/RoomDetailsViewModelTests.swift b/UnitTests/Sources/RoomDetailsViewModelTests.swift index 2759d89e12..bd8e09abe1 100644 --- a/UnitTests/Sources/RoomDetailsViewModelTests.swift +++ b/UnitTests/Sources/RoomDetailsViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -24,14 +15,14 @@ import XCTest @MainActor class RoomDetailsScreenViewModelTests: XCTestCase { var viewModel: RoomDetailsScreenViewModel! - var roomProxyMock: RoomProxyMock! + var roomProxyMock: JoinedRoomProxyMock! var notificationSettingsProxyMock: NotificationSettingsProxyMock! var context: RoomDetailsScreenViewModelType.Context { viewModel.context } var cancellables = Set() override func setUp() { cancellables.removeAll() - roomProxyMock = RoomProxyMock(.init(name: "Test")) + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test")) notificationSettingsProxyMock = NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, clientProxy: ClientProxyMock(.init()), @@ -48,7 +39,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase { func testLeaveRoomTappedWhenPublic() async throws { let mockedMembers: [RoomMemberProxyMock] = [.mockBob, .mockAlice] - roomProxyMock = RoomProxyMock(.init(name: "Test", isPublic: true, members: mockedMembers)) + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isPublic: true, members: mockedMembers)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, clientProxy: ClientProxyMock(.init()), mediaProvider: MockMediaProvider(), @@ -71,7 +62,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase { func testLeaveRoomTappedWhenRoomNotPublic() async throws { let mockedMembers: [RoomMemberProxyMock] = [.mockBob, .mockAlice] - roomProxyMock = RoomProxyMock(.init(name: "Test", isPublic: false, members: mockedMembers)) + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isPublic: false, members: mockedMembers)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, clientProxy: ClientProxyMock(.init()), mediaProvider: MockMediaProvider(), @@ -95,7 +86,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase { func testLeaveRoomTappedWithLessThanTwoMembers() async { let mockedMembers: [RoomMemberProxyMock] = [.mockAlice] - roomProxyMock = RoomProxyMock(.init(name: "Test", isPublic: false, members: mockedMembers)) + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isPublic: false, members: mockedMembers)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, clientProxy: ClientProxyMock(.init()), mediaProvider: MockMediaProvider(), @@ -149,7 +140,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase { func testInitialDMDetailsState() async throws { let recipient = RoomMemberProxyMock.mockDan let mockedMembers: [RoomMemberProxyMock] = [.mockMe, recipient] - roomProxyMock = RoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, clientProxy: ClientProxyMock(.init()), mediaProvider: MockMediaProvider(), @@ -173,7 +164,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase { let recipient = RoomMemberProxyMock.mockDan let mockedMembers: [RoomMemberProxyMock] = [.mockMe, recipient] - roomProxyMock = RoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, clientProxy: ClientProxyMock(.init()), mediaProvider: MockMediaProvider(), @@ -208,7 +199,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase { let mockedMembers: [RoomMemberProxyMock] = [.mockMe, recipient] let clientProxy = ClientProxyMock(.init()) clientProxy.ignoreUserReturnValue = .failure(.sdkError(ClientProxyMockError.generic)) - roomProxyMock = RoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, clientProxy: clientProxy, mediaProvider: MockMediaProvider(), @@ -242,7 +233,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase { func testUnignoreSuccess() async throws { let recipient = RoomMemberProxyMock.mockIgnored let mockedMembers: [RoomMemberProxyMock] = [.mockMe, recipient] - roomProxyMock = RoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, clientProxy: ClientProxyMock(.init()), mediaProvider: MockMediaProvider(), @@ -277,7 +268,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase { let mockedMembers: [RoomMemberProxyMock] = [.mockMe, recipient] let clientProxy = ClientProxyMock(.init()) clientProxy.unignoreUserReturnValue = .failure(.sdkError(ClientProxyMockError.generic)) - roomProxyMock = RoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, clientProxy: clientProxy, mediaProvider: MockMediaProvider(), @@ -310,10 +301,10 @@ class RoomDetailsScreenViewModelTests: XCTestCase { func testCannotInvitePeople() async { let mockedMembers: [RoomMemberProxyMock] = [.mockMe, .mockAlice] - roomProxyMock = RoomProxyMock(.init(name: "Test", - isPublic: true, - members: mockedMembers, - canUserInvite: false)) + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", + isPublic: true, + members: mockedMembers, + canUserInvite: false)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, clientProxy: ClientProxyMock(.init()), mediaProvider: MockMediaProvider(), @@ -331,7 +322,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase { func testInvitePeople() async { let mockedMembers: [RoomMemberProxyMock] = [.mockMe, .mockBob, .mockAlice] - roomProxyMock = RoomProxyMock(.init(name: "Test", isPublic: true, members: mockedMembers)) + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isPublic: true, members: mockedMembers)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, clientProxy: ClientProxyMock(.init()), mediaProvider: MockMediaProvider(), @@ -365,7 +356,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase { func testCanEditAvatar() async { let mockedMembers: [RoomMemberProxyMock] = [.mockMe, .mockBob, .mockAlice] - roomProxyMock = RoomProxyMock(.init(name: "Test", isDirect: false, isPublic: false, members: mockedMembers)) + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, isPublic: false, members: mockedMembers)) roomProxyMock.canUserUserIDSendStateEventClosure = { _, event in .success(event == .roomAvatar) } @@ -389,7 +380,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase { func testCanEditName() async { let mockedMembers: [RoomMemberProxyMock] = [.mockMe, .mockBob, .mockAlice] - roomProxyMock = RoomProxyMock(.init(name: "Test", isDirect: false, isPublic: false, members: mockedMembers)) + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, isPublic: false, members: mockedMembers)) roomProxyMock.canUserUserIDSendStateEventClosure = { _, event in .success(event == .roomName) } @@ -413,7 +404,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase { func testCanEditTopic() async { let mockedMembers: [RoomMemberProxyMock] = [.mockMe, .mockBob, .mockAlice] - roomProxyMock = RoomProxyMock(.init(name: "Test", isDirect: false, isPublic: false, members: mockedMembers)) + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, isPublic: false, members: mockedMembers)) roomProxyMock.canUserUserIDSendStateEventClosure = { _, event in .success(event == .roomTopic) } @@ -437,7 +428,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase { func testCannotEditRoom() async { let mockedMembers: [RoomMemberProxyMock] = [.mockMe, .mockBob, .mockAlice] - roomProxyMock = RoomProxyMock(.init(name: "Test", isDirect: false, isPublic: false, members: mockedMembers)) + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, isPublic: false, members: mockedMembers)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, clientProxy: ClientProxyMock(.init()), mediaProvider: MockMediaProvider(), @@ -458,7 +449,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase { func testCannotEditDirectRoom() async { let mockedMembers: [RoomMemberProxyMock] = [.mockMeAdmin, .mockBob, .mockAlice] - roomProxyMock = RoomProxyMock(.init(name: "Test", isDirect: true, isPublic: false, members: mockedMembers)) + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isPublic: false, members: mockedMembers)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, clientProxy: ClientProxyMock(.init()), mediaProvider: MockMediaProvider(), diff --git a/UnitTests/Sources/RoomDirectorySearchScreenScreenViewModelTests.swift b/UnitTests/Sources/RoomDirectorySearchScreenScreenViewModelTests.swift index 43bac13e20..a0f71e09bb 100644 --- a/UnitTests/Sources/RoomDirectorySearchScreenScreenViewModelTests.swift +++ b/UnitTests/Sources/RoomDirectorySearchScreenScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/RoomFlowCoordinatorTests.swift b/UnitTests/Sources/RoomFlowCoordinatorTests.swift index 5f04315efd..a10fa0f591 100644 --- a/UnitTests/Sources/RoomFlowCoordinatorTests.swift +++ b/UnitTests/Sources/RoomFlowCoordinatorTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest @@ -171,7 +162,7 @@ class RoomFlowCoordinatorTests: XCTestCase { // "Join" the room clientProxy.roomForIdentifierClosure = { _ in - RoomProxyMock(.init()) + .joined(JoinedRoomProxyMock(.init())) } try await process(route: .room(roomID: "InvitedRoomID", via: [])) @@ -201,7 +192,7 @@ class RoomFlowCoordinatorTests: XCTestCase { // "Join" the room clientProxy.roomForIdentifierClosure = { _ in - RoomProxyMock(.init()) + .joined(JoinedRoomProxyMock(.init())) } try await process(route: .room(roomID: "InvitedRoomID", via: [])) @@ -308,6 +299,7 @@ class RoomFlowCoordinatorTests: XCTestCase { roomTimelineControllerFactory: timelineControllerFactory, navigationStackCoordinator: navigationStackCoordinator, emojiProvider: EmojiProvider(), + ongoingCallRoomIDPublisher: .init(.init(nil)), appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, analytics: ServiceLocator.shared.analytics, diff --git a/UnitTests/Sources/RoomListFiltersStateTests.swift b/UnitTests/Sources/RoomListFiltersStateTests.swift index 786330cbd5..9eb9924157 100644 --- a/UnitTests/Sources/RoomListFiltersStateTests.swift +++ b/UnitTests/Sources/RoomListFiltersStateTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/RoomMemberDetailsViewModelTests.swift b/UnitTests/Sources/RoomMemberDetailsViewModelTests.swift index 63bd3827fe..aa79f28b8a 100644 --- a/UnitTests/Sources/RoomMemberDetailsViewModelTests.swift +++ b/UnitTests/Sources/RoomMemberDetailsViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest @@ -21,12 +12,12 @@ import XCTest @MainActor class RoomMemberDetailsViewModelTests: XCTestCase { var viewModel: RoomMemberDetailsScreenViewModelProtocol! - var roomProxyMock: RoomProxyMock! + var roomProxyMock: JoinedRoomProxyMock! var roomMemberProxyMock: RoomMemberProxyMock! var context: RoomMemberDetailsScreenViewModelType.Context { viewModel.context } override func setUp() async throws { - roomProxyMock = RoomProxyMock(.init(name: "")) + roomProxyMock = JoinedRoomProxyMock(.init(name: "")) roomProxyMock.getMemberUserIDClosure = { _ in .success(self.roomMemberProxyMock) diff --git a/UnitTests/Sources/RoomMembersListScreenViewModelTests.swift b/UnitTests/Sources/RoomMembersListScreenViewModelTests.swift index ae2fd28fdf..ba4ccfb24e 100644 --- a/UnitTests/Sources/RoomMembersListScreenViewModelTests.swift +++ b/UnitTests/Sources/RoomMembersListScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest @@ -21,7 +12,7 @@ import XCTest @MainActor class RoomMembersListScreenViewModelTests: XCTestCase { var viewModel: RoomMembersListScreenViewModel! - var roomProxy: RoomProxyMock! + var roomProxy: JoinedRoomProxyMock! var context: RoomMembersListScreenViewModel.Context { viewModel.context @@ -148,7 +139,7 @@ class RoomMembersListScreenViewModelTests: XCTestCase { func testSelectUserAsAdmin() async throws { // Given the room list viewed as an admin. setup(with: .allMembersAsAdmin) - var deferred = deferFulfillment(context.$viewState) { !$0.visibleInvitedMembers.isEmpty } + var deferred = deferFulfillment(context.$viewState) { !$0.visibleInvitedMembers.isEmpty && $0.canKickUsers && $0.canBanUsers } try await deferred.fulfill() XCTAssertNil(context.memberToManage) @@ -169,7 +160,7 @@ class RoomMembersListScreenViewModelTests: XCTestCase { func testSelectModeratorAsAdmin() async throws { // Given the room list viewed as an admin. setup(with: .allMembersAsAdmin) - var deferred = deferFulfillment(context.$viewState) { !$0.visibleInvitedMembers.isEmpty } + var deferred = deferFulfillment(context.$viewState) { !$0.visibleInvitedMembers.isEmpty && $0.canKickUsers && $0.canBanUsers } try await deferred.fulfill() XCTAssertNil(context.memberToManage) @@ -286,7 +277,7 @@ class RoomMembersListScreenViewModelTests: XCTestCase { } private func setup(with members: [RoomMemberProxyMock]) { - roomProxy = RoomProxyMock(.init(name: "test", members: members)) + roomProxy = JoinedRoomProxyMock(.init(name: "test", members: members)) viewModel = .init(roomProxy: roomProxy, mediaProvider: MockMediaProvider(), userIndicatorController: ServiceLocator.shared.userIndicatorController, diff --git a/UnitTests/Sources/RoomNotificationSettingsScreenViewModelTests.swift b/UnitTests/Sources/RoomNotificationSettingsScreenViewModelTests.swift index 93a83812bb..472ce13a44 100644 --- a/UnitTests/Sources/RoomNotificationSettingsScreenViewModelTests.swift +++ b/UnitTests/Sources/RoomNotificationSettingsScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -22,18 +13,18 @@ import XCTest @MainActor class RoomNotificationSettingsScreenViewModelTests: XCTestCase { - var roomProxyMock: RoomProxyMock! + var roomProxyMock: JoinedRoomProxyMock! var notificationSettingsProxyMock: NotificationSettingsProxyMock! var cancellables = Set() override func setUpWithError() throws { cancellables.removeAll() - roomProxyMock = RoomProxyMock(.init(name: "Test")) + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test")) notificationSettingsProxyMock = NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()) } func testInitialStateDefaultModeEncryptedRoom() async throws { - let roomProxyMock = RoomProxyMock(.init(name: "Test", isEncrypted: true)) + let roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isEncrypted: true)) let notificationSettingsProxyMock = NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()) notificationSettingsProxyMock.getNotificationSettingsRoomIdIsEncryptedIsOneToOneReturnValue = RoomNotificationSettingsProxyMock(with: .init(mode: .mentionsAndKeywordsOnly, isDefault: true)) @@ -55,7 +46,7 @@ class RoomNotificationSettingsScreenViewModelTests: XCTestCase { } func testInitialStateDefaultModeEncryptedRoomWithCanPushEncrypted() async throws { - let roomProxyMock = RoomProxyMock(.init(name: "Test", isEncrypted: true)) + let roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isEncrypted: true)) let notificationSettingsProxyMock = NotificationSettingsProxyMock(with: .init(canPushEncryptedEvents: true)) notificationSettingsProxyMock.getNotificationSettingsRoomIdIsEncryptedIsOneToOneReturnValue = RoomNotificationSettingsProxyMock(with: .init(mode: .mentionsAndKeywordsOnly, isDefault: true)) @@ -77,7 +68,7 @@ class RoomNotificationSettingsScreenViewModelTests: XCTestCase { } func testInitialStateDefaultModeUnencryptedRoom() async throws { - let roomProxyMock = RoomProxyMock(.init(name: "Test", isEncrypted: false)) + let roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isEncrypted: false)) let notificationSettingsProxyMock = NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()) notificationSettingsProxyMock.getNotificationSettingsRoomIdIsEncryptedIsOneToOneReturnValue = RoomNotificationSettingsProxyMock(with: .init(mode: .mentionsAndKeywordsOnly, isDefault: true)) diff --git a/UnitTests/Sources/RoomPermissionsTests.swift b/UnitTests/Sources/RoomPermissionsTests.swift index 6fbc74a72c..acd77636f5 100644 --- a/UnitTests/Sources/RoomPermissionsTests.swift +++ b/UnitTests/Sources/RoomPermissionsTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import MatrixRustSDK diff --git a/UnitTests/Sources/RoomPollsHistoryScreenViewModelTests.swift b/UnitTests/Sources/RoomPollsHistoryScreenViewModelTests.swift index 01cec1c4a7..7550f9dfb7 100644 --- a/UnitTests/Sources/RoomPollsHistoryScreenViewModelTests.swift +++ b/UnitTests/Sources/RoomPollsHistoryScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/RoomRolesAndPermissionsScreenViewModelTests.swift b/UnitTests/Sources/RoomRolesAndPermissionsScreenViewModelTests.swift index 1ce826e566..c37c4c63c9 100644 --- a/UnitTests/Sources/RoomRolesAndPermissionsScreenViewModelTests.swift +++ b/UnitTests/Sources/RoomRolesAndPermissionsScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest @@ -21,7 +12,7 @@ import XCTest @MainActor class RoomRolesAndPermissionsScreenViewModelTests: XCTestCase { var viewModel: RoomRolesAndPermissionsScreenViewModelProtocol! - var roomProxy: RoomProxyMock! + var roomProxy: JoinedRoomProxyMock! var context: RoomRolesAndPermissionsScreenViewModelType.Context { viewModel.context @@ -83,7 +74,7 @@ class RoomRolesAndPermissionsScreenViewModelTests: XCTestCase { } private func setupViewModel(members: [RoomMemberProxyMock]) { - roomProxy = RoomProxyMock(.init(members: members)) + roomProxy = JoinedRoomProxyMock(.init(members: members)) viewModel = RoomRolesAndPermissionsScreenViewModel(roomProxy: roomProxy, userIndicatorController: UserIndicatorControllerMock(), analytics: ServiceLocator.shared.analytics) diff --git a/UnitTests/Sources/RoomScreenViewModelTests.swift b/UnitTests/Sources/RoomScreenViewModelTests.swift index 0d837da72a..a7998b4dce 100644 --- a/UnitTests/Sources/RoomScreenViewModelTests.swift +++ b/UnitTests/Sources/RoomScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @testable import ElementX @@ -21,418 +12,222 @@ import XCTest @MainActor class RoomScreenViewModelTests: XCTestCase { - var userIndicatorControllerMock: UserIndicatorControllerMock! - var cancellables = Set() - + private var viewModel: RoomScreenViewModel! + override func setUp() async throws { AppSettings.resetAllSettings() - cancellables.removeAll() - userIndicatorControllerMock = UserIndicatorControllerMock.default - } - - override func tearDown() async throws { - userIndicatorControllerMock = nil - } - - // MARK: - Message Grouping - - func testMessageGrouping() { - // Given 3 messages from Bob. - let items = [ - TextRoomTimelineItem(text: "Message 1", - sender: "bob"), - TextRoomTimelineItem(text: "Message 2", - sender: "bob"), - TextRoomTimelineItem(text: "Message 3", - sender: "bob") - ] - - // When showing them in a timeline. - let timelineController = MockRoomTimelineController() - timelineController.timelineItems = items - let viewModel = makeViewModel(timelineController: timelineController) - - // Then the messages should be grouped together. - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .first, "Nothing should prevent the first message from being grouped.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[1].groupStyle, .middle, "Nothing should prevent the middle message from being grouped.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[2].groupStyle, .last, "Nothing should prevent the last message from being grouped.") - } - - func testMessageGroupingMultipleSenders() { - // Given some interleaved messages from Bob and Alice. - let items = [ - TextRoomTimelineItem(text: "Message 1", - sender: "alice"), - TextRoomTimelineItem(text: "Message 2", - sender: "bob"), - TextRoomTimelineItem(text: "Message 3", - sender: "alice"), - TextRoomTimelineItem(text: "Message 4", - sender: "alice"), - TextRoomTimelineItem(text: "Message 5", - sender: "bob"), - TextRoomTimelineItem(text: "Message 6", - sender: "bob") - ] - - // When showing them in a timeline. - let timelineController = MockRoomTimelineController() - timelineController.timelineItems = items - let viewModel = makeViewModel(timelineController: timelineController) - - // Then the messages should be grouped by sender. - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .single, "A message should not be grouped when the sender changes.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[1].groupStyle, .single, "A message should not be grouped when the sender changes.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[2].groupStyle, .first, "A group should start with a new sender if there are more messages from that sender.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[3].groupStyle, .last, "A group should be ended when the sender changes in the next message.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[4].groupStyle, .first, "A group should start with a new sender if there are more messages from that sender.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[5].groupStyle, .last, "A group should be ended when the sender changes in the next message.") - } - - func testMessageGroupingWithLeadingReactions() { - // Given 3 messages from Bob where the first message has a reaction. - let items = [ - TextRoomTimelineItem(text: "Message 1", - sender: "bob", - addReactions: true), - TextRoomTimelineItem(text: "Message 2", - sender: "bob"), - TextRoomTimelineItem(text: "Message 3", - sender: "bob") - ] - - // When showing them in a timeline. - let timelineController = MockRoomTimelineController() - timelineController.timelineItems = items - let viewModel = makeViewModel(timelineController: timelineController) - - // Then the first message should not be grouped but the other two should. - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .single, "When the first message has reactions it should not be grouped.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[1].groupStyle, .first, "A new group should be made when the preceding message has reactions.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[2].groupStyle, .last, "Nothing should prevent the last message from being grouped.") - } - - func testMessageGroupingWithInnerReactions() { - // Given 3 messages from Bob where the middle message has a reaction. - let items = [ - TextRoomTimelineItem(text: "Message 1", - sender: "bob"), - TextRoomTimelineItem(text: "Message 2", - sender: "bob", - addReactions: true), - TextRoomTimelineItem(text: "Message 3", - sender: "bob") - ] - - // When showing them in a timeline. - let timelineController = MockRoomTimelineController() - timelineController.timelineItems = items - let viewModel = makeViewModel(timelineController: timelineController) - - // Then the first and second messages should be grouped and the last one should not. - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .first, "Nothing should prevent the first message from being grouped.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[1].groupStyle, .last, "When the message has reactions, the group should end here.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[2].groupStyle, .single, "The last message should not be grouped when the preceding message has reactions.") } - func testMessageGroupingWithTrailingReactions() { - // Given 3 messages from Bob where the last message has a reaction. - let items = [ - TextRoomTimelineItem(text: "Message 1", - sender: "bob"), - TextRoomTimelineItem(text: "Message 2", - sender: "bob"), - TextRoomTimelineItem(text: "Message 3", - sender: "bob", - addReactions: true) - ] - - // When showing them in a timeline. - let timelineController = MockRoomTimelineController() - timelineController.timelineItems = items - let viewModel = makeViewModel(timelineController: timelineController) - - // Then the messages should be grouped together. - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .first, "Nothing should prevent the first message from being grouped.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[1].groupStyle, .middle, "Nothing should prevent the second message from being grouped.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[2].groupStyle, .last, "Reactions on the last message should not prevent it from being grouped.") + override func tearDown() { + viewModel = nil } - // MARK: - Focussing - - func testFocusItem() async throws { - // Given a room with 3 items loaded in a live timeline. - let items = [TextRoomTimelineItem(eventID: "t1"), - TextRoomTimelineItem(eventID: "t2"), - TextRoomTimelineItem(eventID: "t3")] - let timelineController = MockRoomTimelineController() - timelineController.timelineItems = items - - let viewModel = makeViewModel(timelineController: timelineController) - XCTAssertEqual(timelineController.focusOnEventCallCount, 0) - XCTAssertTrue(viewModel.context.viewState.timelineViewState.isLive) - XCTAssertNil(viewModel.context.viewState.timelineViewState.focussedEvent) + func testPinnedEventsBanner() async throws { + ServiceLocator.shared.settings.pinningEnabled = true + let timelineSubject = PassthroughSubject() + let updateSubject = PassthroughSubject() + let roomProxyMock = JoinedRoomProxyMock(.init()) + // setup a way to inject the mock of the pinned events timeline + roomProxyMock.pinnedEventsTimelineClosure = { + await timelineSubject.values.first() + } + // setup the room proxy actions publisher + roomProxyMock.underlyingActionsPublisher = updateSubject.eraseToAnyPublisher() + let viewModel = RoomScreenViewModel(roomProxy: roomProxyMock, + initialSelectedPinnedEventID: nil, + mediaProvider: MockMediaProvider(), + ongoingCallRoomIDPublisher: .init(.init(nil)), + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) + self.viewModel = viewModel - // When focussing on an item that isn't loaded. - let deferred = deferFulfillment(viewModel.context.$viewState) { !$0.timelineViewState.isLive } - await viewModel.focusOnEvent(eventID: "t4") + // check if in the default state is not showing but is indeed loading + var deferred = deferFulfillment(viewModel.context.$viewState) { viewState in + viewState.pinnedEventsBannerState.count == 0 + } try await deferred.fulfill() - - // Then a new timeline should be loaded and the room focussed on that event. - XCTAssertEqual(timelineController.focusOnEventCallCount, 1) - XCTAssertFalse(viewModel.context.viewState.timelineViewState.isLive) - XCTAssertEqual(viewModel.context.viewState.timelineViewState.focussedEvent, .init(eventID: "t4", appearance: .immediate)) - } - - func testFocusLoadedItem() async throws { - // Given a room with 3 items loaded in a live timeline. - let items = [TextRoomTimelineItem(eventID: "t1"), - TextRoomTimelineItem(eventID: "t2"), - TextRoomTimelineItem(eventID: "t3")] - let timelineController = MockRoomTimelineController() - timelineController.timelineItems = items - - let viewModel = makeViewModel(timelineController: timelineController) - XCTAssertEqual(timelineController.focusOnEventCallCount, 0) - XCTAssertTrue(viewModel.context.viewState.timelineViewState.isLive) - XCTAssertNil(viewModel.context.viewState.timelineViewState.focussedEvent) - - // When focussing on a loaded item. - let deferred = deferFailure(viewModel.context.$viewState, timeout: 1) { !$0.timelineViewState.isLive } - await viewModel.focusOnEvent(eventID: "t1") + XCTAssertTrue(viewModel.context.viewState.pinnedEventsBannerState.isLoading) + XCTAssertFalse(viewModel.context.viewState.shouldShowPinnedEventsBanner) + + // check if if after the pinned event ids are set the banner is still in a loading state, but is both loading and showing with a counter + deferred = deferFulfillment(viewModel.context.$viewState) { viewState in + viewState.pinnedEventsBannerState.count == 2 + } + roomProxyMock.underlyingPinnedEventIDs = ["test1", "test2"] + updateSubject.send(.roomInfoUpdate) try await deferred.fulfill() - - // Then the timeline should remain live and the item should be focussed. - XCTAssertEqual(timelineController.focusOnEventCallCount, 0) - XCTAssertTrue(viewModel.context.viewState.timelineViewState.isLive) - XCTAssertEqual(viewModel.context.viewState.timelineViewState.focussedEvent, .init(eventID: "t1", appearance: .animated)) - } - - func testFocusLive() async throws { - // Given a room with a non-live timeline focussed on a particular event. - let items = [TextRoomTimelineItem(eventID: "t1"), - TextRoomTimelineItem(eventID: "t2"), - TextRoomTimelineItem(eventID: "t3")] - let timelineController = MockRoomTimelineController() - timelineController.timelineItems = items - - let viewModel = makeViewModel(timelineController: timelineController) - - var deferred = deferFulfillment(viewModel.context.$viewState) { !$0.timelineViewState.isLive } - await viewModel.focusOnEvent(eventID: "t4") + XCTAssertTrue(viewModel.context.viewState.pinnedEventsBannerState.isLoading) + XCTAssertTrue(viewModel.context.viewState.shouldShowPinnedEventsBanner) + XCTAssertEqual(viewModel.context.viewState.pinnedEventsBannerState.selectedPinnedIndex, 1) + + // setup the loaded pinned events injection in the timeline + let pinnedTimelineMock = TimelineProxyMock() + let pinnedTimelineProviderMock = RoomTimelineProviderMock() + let providerUpdateSubject = PassthroughSubject<([TimelineItemProxy], PaginationState), Never>() + pinnedTimelineProviderMock.underlyingUpdatePublisher = providerUpdateSubject.eraseToAnyPublisher() + pinnedTimelineMock.timelineProvider = pinnedTimelineProviderMock + pinnedTimelineProviderMock.itemProxies = [.event(.init(item: EventTimelineItemSDKMock(configuration: .init(eventID: "test1")), id: "1")), + .event(.init(item: EventTimelineItemSDKMock(configuration: .init(eventID: "test2")), id: "2"))] + + // check if the banner is now in a loaded state and is showing the counter + deferred = deferFulfillment(viewModel.context.$viewState) { viewState in + !viewState.pinnedEventsBannerState.isLoading + } + timelineSubject.send(pinnedTimelineMock) try await deferred.fulfill() + XCTAssertEqual(viewModel.context.viewState.pinnedEventsBannerState.count, 2) + XCTAssertTrue(viewModel.context.viewState.shouldShowPinnedEventsBanner) + XCTAssertEqual(viewModel.context.viewState.pinnedEventsBannerState.selectedPinnedIndex, 1) - XCTAssertEqual(timelineController.focusLiveCallCount, 0) - XCTAssertFalse(viewModel.context.viewState.timelineViewState.isLive) - XCTAssertEqual(viewModel.context.viewState.timelineViewState.focussedEvent, .init(eventID: "t4", appearance: .immediate)) - - // When switching back to a live timeline. - deferred = deferFulfillment(viewModel.context.$viewState) { $0.timelineViewState.isLive } - viewModel.context.send(viewAction: .focusLive) + // check if the banner is updating alongside the timeline + deferred = deferFulfillment(viewModel.context.$viewState) { viewState in + viewState.pinnedEventsBannerState.count == 3 + } + providerUpdateSubject.send(([.event(.init(item: EventTimelineItemSDKMock(configuration: .init(eventID: "test1")), id: "1")), + .event(.init(item: EventTimelineItemSDKMock(configuration: .init(eventID: "test2")), id: "2")), + .event(.init(item: EventTimelineItemSDKMock(configuration: .init(eventID: "test3")), id: "3"))], .initial)) try await deferred.fulfill() + XCTAssertFalse(viewModel.context.viewState.pinnedEventsBannerState.isLoading) + XCTAssertTrue(viewModel.context.viewState.shouldShowPinnedEventsBanner) + XCTAssertEqual(viewModel.context.viewState.pinnedEventsBannerState.selectedPinnedIndex, 1) + + // check how the scrolling changes the banner visibility + viewModel.timelineHasScrolled(direction: .top) + XCTAssertFalse(viewModel.context.viewState.shouldShowPinnedEventsBanner) + + viewModel.timelineHasScrolled(direction: .bottom) + XCTAssertTrue(viewModel.context.viewState.shouldShowPinnedEventsBanner) + } + + func testPinnedEventsBannerSelection() async throws { + ServiceLocator.shared.settings.pinningEnabled = true + let roomProxyMock = JoinedRoomProxyMock(.init()) + // setup a way to inject the mock of the pinned events timeline + let pinnedTimelineMock = TimelineProxyMock() + let pinnedTimelineProviderMock = RoomTimelineProviderMock() + pinnedTimelineMock.timelineProvider = pinnedTimelineProviderMock + pinnedTimelineProviderMock.underlyingUpdatePublisher = Empty<([TimelineItemProxy], PaginationState), Never>().eraseToAnyPublisher() + pinnedTimelineProviderMock.itemProxies = [.event(.init(item: EventTimelineItemSDKMock(configuration: .init(eventID: "test1")), id: "1")), + .event(.init(item: EventTimelineItemSDKMock(configuration: .init(eventID: "test2")), id: "2")), + .event(.init(item: EventTimelineItemSDKMock(configuration: .init(eventID: "test3")), id: "3"))] + roomProxyMock.underlyingPinnedEventsTimeline = pinnedTimelineMock + let viewModel = RoomScreenViewModel(roomProxy: roomProxyMock, + initialSelectedPinnedEventID: "test1", + mediaProvider: MockMediaProvider(), + ongoingCallRoomIDPublisher: .init(.init(nil)), + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) + self.viewModel = viewModel - // Then the timeline should switch back to being live and the event focus should be removed. - XCTAssertEqual(timelineController.focusLiveCallCount, 1) - XCTAssertTrue(viewModel.context.viewState.timelineViewState.isLive) - XCTAssertNil(viewModel.context.viewState.timelineViewState.focussedEvent) - } - - func testInitialFocusViewState() async throws { - let timelineController = MockRoomTimelineController() - - let viewModel = makeViewModel(focussedEventID: "t10", timelineController: timelineController) - XCTAssertEqual(viewModel.context.viewState.timelineViewState.focussedEvent, .init(eventID: "t10", appearance: .immediate)) - } - - // MARK: - Read Receipts - - // swiftlint:disable force_unwrapping - func testSendReadReceipt() async throws { - // Given a room with only text items in the timeline - let items = [TextRoomTimelineItem(eventID: "t1"), - TextRoomTimelineItem(eventID: "t2"), - TextRoomTimelineItem(eventID: "t3")] - let (viewModel, _, timelineProxy, _) = readReceiptsConfiguration(with: items) - - // When sending a read receipt for the last item. - viewModel.context.send(viewAction: .sendReadReceiptIfNeeded(items.last!.id)) - try await Task.sleep(for: .milliseconds(100)) + // check if the banner is now in a loaded state and is showing the counter + var deferred = deferFulfillment(viewModel.context.$viewState) { viewState in + !viewState.pinnedEventsBannerState.isLoading + } + try await deferred.fulfill() + XCTAssertEqual(viewModel.context.viewState.pinnedEventsBannerState.count, 3) + XCTAssertTrue(viewModel.context.viewState.shouldShowPinnedEventsBanner) + // And that is actually displaying the `initialSelectedPinEventID` which is gthe first one in the list + XCTAssertEqual(viewModel.context.viewState.pinnedEventsBannerState.selectedPinnedIndex, 0) + + // check if the banner scrolls when tapping the previous pin + deferred = deferFulfillment(viewModel.context.$viewState) { viewState in + viewState.pinnedEventsBannerState.selectedPinnedIndex == 2 + } + let deferredAction = deferFulfillment(viewModel.actions) { action in + if case let .focusEvent(eventID) = action { + return eventID == "test1" + } + return false + } + viewModel.context.send(viewAction: .tappedPinnedEventsBanner) + try await deferred.fulfill() + try await deferredAction.fulfill() - // Then the receipt should be sent. - XCTAssertEqual(timelineProxy.sendReadReceiptForTypeCalled, true) - let arguments = timelineProxy.sendReadReceiptForTypeReceivedArguments - XCTAssertEqual(arguments?.eventID, "t3") - XCTAssertEqual(arguments?.type, .read) + // check if the banner scrolls to the specific selected pin + deferred = deferFulfillment(viewModel.context.$viewState) { viewState in + viewState.pinnedEventsBannerState.selectedPinnedIndex == 1 + } + viewModel.setSelectedPinnedEventID("test2") + try await deferred.fulfill() } - func testSendMoreReadReceipts() async throws { - // Given a room with only text items in the timeline that are all read. - let items = [TextRoomTimelineItem(eventID: "t1"), - TextRoomTimelineItem(eventID: "t2"), - TextRoomTimelineItem(eventID: "t3")] - let (viewModel, _, timelineProxy, timelineController) = readReceiptsConfiguration(with: items) - viewModel.context.send(viewAction: .sendReadReceiptIfNeeded(items.last!.id)) - try await Task.sleep(for: .milliseconds(100)) - XCTAssertEqual(timelineProxy.sendReadReceiptForTypeCallsCount, 1) - var arguments = timelineProxy.sendReadReceiptForTypeReceivedArguments - XCTAssertEqual(arguments?.eventID, "t3") - XCTAssertEqual(arguments?.type, .read) - - // When sending a receipt for the first item in the timeline. - viewModel.context.send(viewAction: .sendReadReceiptIfNeeded(items.first!.id)) - try await Task.sleep(for: .milliseconds(100)) - - // When a new message is received and marked as read. - let newMessage = TextRoomTimelineItem(eventID: "t4") - timelineController.timelineItems.append(newMessage) - timelineController.callbacks.send(.updatedTimelineItems(timelineItems: timelineController.timelineItems, isSwitchingTimelines: false)) - try await Task.sleep(for: .milliseconds(100)) - - viewModel.context.send(viewAction: .sendReadReceiptIfNeeded(newMessage.id)) - try await Task.sleep(for: .milliseconds(100)) + func testRoomInfoUpdate() async throws { + let updateSubject = PassthroughSubject() + let roomProxyMock = JoinedRoomProxyMock(.init(id: "TestID", name: "StartingName", avatarURL: nil, hasOngoingCall: false)) + // setup the room proxy actions publisher + roomProxyMock.canUserJoinCallUserIDReturnValue = .success(false) + roomProxyMock.underlyingActionsPublisher = updateSubject.eraseToAnyPublisher() + let viewModel = RoomScreenViewModel(roomProxy: roomProxyMock, + initialSelectedPinnedEventID: nil, + mediaProvider: MockMediaProvider(), + ongoingCallRoomIDPublisher: .init(.init(nil)), + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) + self.viewModel = viewModel - // Then the request should be made. - XCTAssertEqual(timelineProxy.sendReadReceiptForTypeCallsCount, 3) - arguments = timelineProxy.sendReadReceiptForTypeReceivedArguments - XCTAssertEqual(arguments?.eventID, "t4") - XCTAssertEqual(arguments?.type, .read) - } - - func testSendReadReceiptWithoutEvents() async throws { - // Given a room with only virtual items. - let items = [SeparatorRoomTimelineItem(timelineID: "v1"), - SeparatorRoomTimelineItem(timelineID: "v2"), - SeparatorRoomTimelineItem(timelineID: "v3")] - let (viewModel, _, timelineProxy, _) = readReceiptsConfiguration(with: items) + var deferred = deferFulfillment(viewModel.context.$viewState) { viewState in + viewState.roomTitle == "StartingName" && + viewState.roomAvatar == .room(id: "TestID", name: "StartingName", avatarURL: nil) && + !viewState.canJoinCall && + !viewState.hasOngoingCall + } + try await deferred.fulfill() - // When sending a read receipt for the last item. - viewModel.context.send(viewAction: .sendReadReceiptIfNeeded(items.last!.id)) - try await Task.sleep(for: .milliseconds(100)) + roomProxyMock.name = "NewName" + roomProxyMock.avatar = .room(id: "TestID", name: "NewName", avatarURL: .documentsDirectory) + roomProxyMock.hasOngoingCall = true + roomProxyMock.canUserJoinCallUserIDReturnValue = .success(true) - // Then nothing should be sent. - XCTAssertEqual(timelineProxy.sendReadReceiptForTypeCalled, false) - } - - func testSendReadReceiptVirtualLast() async throws { - // Given a room where the last event is a virtual item. - let items: [RoomTimelineItemProtocol] = [TextRoomTimelineItem(eventID: "t1"), - TextRoomTimelineItem(eventID: "t2"), - SeparatorRoomTimelineItem(timelineID: "v3")] - let (viewModel, _, _, _) = readReceiptsConfiguration(with: items) + deferred = deferFulfillment(viewModel.context.$viewState) { viewState in + viewState.roomTitle == "NewName" && + viewState.roomAvatar == .room(id: "TestID", name: "NewName", avatarURL: .documentsDirectory) && + viewState.canJoinCall && + viewState.hasOngoingCall + } - // When sending a read receipt for the last item. - viewModel.context.send(viewAction: .sendReadReceiptIfNeeded(items.last!.id)) - try await Task.sleep(for: .milliseconds(100)) + updateSubject.send(.roomInfoUpdate) + try await deferred.fulfill() } - // swiftlint:enable force_unwrapping - // swiftlint:disable:next large_tuple - private func readReceiptsConfiguration(with items: [RoomTimelineItemProtocol]) -> (RoomScreenViewModel, - RoomProxyMock, - TimelineProxyMock, - MockRoomTimelineController) { - let roomProxy = RoomProxyMock(.init(name: "")) - - let timelineProxy = TimelineProxyMock() - - roomProxy.timeline = timelineProxy - let timelineController = MockRoomTimelineController() - - timelineProxy.sendReadReceiptForTypeReturnValue = .success(()) - - timelineController.timelineItems = items - timelineController.roomProxy = roomProxy - - let viewModel = RoomScreenViewModel(roomProxy: roomProxy, - timelineController: timelineController, + func testCallButtonVisibility() async throws { + // Given a room screen with no ongoing call. + let ongoingCallRoomIDSubject = CurrentValueSubject(nil) + let roomProxyMock = JoinedRoomProxyMock(.init(id: "MyRoomID")) + let viewModel = RoomScreenViewModel(roomProxy: roomProxyMock, + initialSelectedPinnedEventID: nil, mediaProvider: MockMediaProvider(), - mediaPlayerProvider: MediaPlayerProviderMock(), - voiceMessageMediaManager: VoiceMessageMediaManagerMock(), - userIndicatorController: userIndicatorControllerMock, + ongoingCallRoomIDPublisher: ongoingCallRoomIDSubject.asCurrentValuePublisher(), appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, analyticsService: ServiceLocator.shared.analytics) - return (viewModel, roomProxy, timelineProxy, timelineController) - } - - func testShowReadReceipts() async throws { - let receipts: [ReadReceipt] = [.init(userID: "@alice:matrix.org", formattedTimestamp: "12:00"), - .init(userID: "@charlie:matrix.org", formattedTimestamp: "11:00")] - // Given 3 messages from Bob where the middle message has a reaction. - let message = TextRoomTimelineItem(text: "Test", - sender: "bob", - addReadReceipts: receipts) - let id = message.id + self.viewModel = viewModel + XCTAssertTrue(viewModel.state.shouldShowCallButton) - // When showing them in a timeline. - let timelineController = MockRoomTimelineController() - timelineController.timelineItems = [message] - let viewModel = RoomScreenViewModel(roomProxy: RoomProxyMock(.init(name: "", members: [RoomMemberProxyMock.mockAlice, RoomMemberProxyMock.mockCharlie])), - timelineController: timelineController, - mediaProvider: MockMediaProvider(), - mediaPlayerProvider: MediaPlayerProviderMock(), - voiceMessageMediaManager: VoiceMessageMediaManagerMock(), - userIndicatorController: userIndicatorControllerMock, - appMediator: AppMediatorMock.default, - appSettings: ServiceLocator.shared.settings, - analyticsService: ServiceLocator.shared.analytics) + // When a call starts in this room. + var deferred = deferFulfillment(viewModel.context.$viewState) { !$0.shouldShowCallButton } + ongoingCallRoomIDSubject.send("MyRoomID") + try await deferred.fulfill() - let deferred = deferFulfillment(viewModel.context.$viewState) { value in - value.bindings.readReceiptsSummaryInfo?.orderedReceipts == receipts - } + // Then the call button should be hidden. + XCTAssertFalse(viewModel.state.shouldShowCallButton) - viewModel.context.send(viewAction: .displayReadReceipts(itemID: id)) + // When a call starts in a different room. + deferred = deferFulfillment(viewModel.context.$viewState) { $0.shouldShowCallButton } + ongoingCallRoomIDSubject.send("OtherRoomID") try await deferred.fulfill() - } - - // MARK: - Helpers - - private func makeViewModel(roomProxy: RoomProxyProtocol? = nil, - focussedEventID: String? = nil, - timelineController: RoomTimelineControllerProtocol) -> RoomScreenViewModel { - RoomScreenViewModel(roomProxy: roomProxy ?? RoomProxyMock(.init(name: "")), - focussedEventID: focussedEventID, - timelineController: timelineController, - mediaProvider: MockMediaProvider(), - mediaPlayerProvider: MediaPlayerProviderMock(), - voiceMessageMediaManager: VoiceMessageMediaManagerMock(), - userIndicatorController: userIndicatorControllerMock, - appMediator: AppMediatorMock.default, - appSettings: ServiceLocator.shared.settings, - analyticsService: ServiceLocator.shared.analytics) - } -} - -private extension TextRoomTimelineItem { - init(text: String, sender: String, addReactions: Bool = false, addReadReceipts: [ReadReceipt] = []) { - let reactions = addReactions ? [AggregatedReaction(accountOwnerID: "bob", key: "๐Ÿฆ„", senders: [ReactionSender(id: sender, timestamp: Date())])] : [] - self.init(id: .random, - timestamp: "10:47 am", - isOutgoing: sender == "bob", - isEditable: sender == "bob", - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "@\(sender):server.com", displayName: sender), - content: .init(body: text), - properties: RoomTimelineItemProperties(reactions: reactions, orderedReadReceipts: addReadReceipts)) - } -} - -private extension SeparatorRoomTimelineItem { - init(timelineID: String) { - self.init(id: .init(timelineID: timelineID), text: "") - } -} - -private extension TextRoomTimelineItem { - init(eventID: String) { - self.init(id: .init(timelineID: UUID().uuidString, eventID: eventID), - timestamp: "", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: ""), - content: .init(body: "Hello, World!")) + + // Then the call button should be shown again. + XCTAssertTrue(viewModel.state.shouldShowCallButton) + + // When the call from the other room finishes. + let deferredFailure = deferFailure(viewModel.context.$viewState, timeout: 1) { !$0.shouldShowCallButton } + ongoingCallRoomIDSubject.send(nil) + try await deferredFailure.fulfill() + + // Then the call button should remain visible shown. + XCTAssertTrue(viewModel.state.shouldShowCallButton) } } diff --git a/UnitTests/Sources/RoomStateEventStringBuilderTests.swift b/UnitTests/Sources/RoomStateEventStringBuilderTests.swift index a886fe3468..524997f50d 100644 --- a/UnitTests/Sources/RoomStateEventStringBuilderTests.swift +++ b/UnitTests/Sources/RoomStateEventStringBuilderTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @testable import ElementX diff --git a/UnitTests/Sources/RoomSummaryTests.swift b/UnitTests/Sources/RoomSummaryTests.swift index 444efb0f04..55cb93948d 100644 --- a/UnitTests/Sources/RoomSummaryTests.swift +++ b/UnitTests/Sources/RoomSummaryTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/SecureBackupKeyBackupScreenViewModelTests.swift b/UnitTests/Sources/SecureBackupKeyBackupScreenViewModelTests.swift index 2d108dc80f..4a1b49d91c 100644 --- a/UnitTests/Sources/SecureBackupKeyBackupScreenViewModelTests.swift +++ b/UnitTests/Sources/SecureBackupKeyBackupScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/SecureBackupLogoutConfirmationScreenViewModelTests.swift b/UnitTests/Sources/SecureBackupLogoutConfirmationScreenViewModelTests.swift index 7b0ec31975..6386b923eb 100644 --- a/UnitTests/Sources/SecureBackupLogoutConfirmationScreenViewModelTests.swift +++ b/UnitTests/Sources/SecureBackupLogoutConfirmationScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/SecureBackupRecoveryKeyScreenViewModelTests.swift b/UnitTests/Sources/SecureBackupRecoveryKeyScreenViewModelTests.swift index d6b6ac487d..c441de3052 100644 --- a/UnitTests/Sources/SecureBackupRecoveryKeyScreenViewModelTests.swift +++ b/UnitTests/Sources/SecureBackupRecoveryKeyScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/SecureBackupScreenViewModelTests.swift b/UnitTests/Sources/SecureBackupScreenViewModelTests.swift index 3ea215ef92..a045f3621c 100644 --- a/UnitTests/Sources/SecureBackupScreenViewModelTests.swift +++ b/UnitTests/Sources/SecureBackupScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/ServerConfigurationScreenViewStateTests.swift b/UnitTests/Sources/ServerConfigurationScreenViewStateTests.swift index 1126941a2e..b859e17414 100644 --- a/UnitTests/Sources/ServerConfigurationScreenViewStateTests.swift +++ b/UnitTests/Sources/ServerConfigurationScreenViewStateTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest @@ -34,12 +25,19 @@ class ServerConfirmationScreenViewStateTests: XCTestCase { } func testRegisterMessageString() { - let matrixDotOrgLogin = ServerConfirmationScreenViewState(homeserverAddress: LoginHomeserver.mockMatrixDotOrg.address, - authenticationFlow: .register) - XCTAssertEqual(matrixDotOrgLogin.message, L10n.screenServerConfirmationMessageRegister, "The registration message should always be the same.") + let matrixDotOrgRegister = ServerConfirmationScreenViewState(homeserverAddress: LoginHomeserver.mockMatrixDotOrg.address, + authenticationFlow: .register, + homeserverSupportsRegistration: true) + XCTAssertEqual(matrixDotOrgRegister.message, L10n.screenServerConfirmationMessageRegister, "The registration message should always be the same.") - let otherLogin = ServerConfirmationScreenViewState(homeserverAddress: LoginHomeserver.mockOIDC.address, - authenticationFlow: .register) - XCTAssertEqual(otherLogin.message, L10n.screenServerConfirmationMessageRegister, "The registration message should always be the same.") + let oidcRegister = ServerConfirmationScreenViewState(homeserverAddress: LoginHomeserver.mockOIDC.address, + authenticationFlow: .register, + homeserverSupportsRegistration: true) + XCTAssertEqual(oidcRegister.message, L10n.screenServerConfirmationMessageRegister, "The registration message should always be the same.") + + let otherRegister = ServerConfirmationScreenViewState(homeserverAddress: LoginHomeserver.mockBasicServer.address, + authenticationFlow: .register, + homeserverSupportsRegistration: false) + XCTAssertEqual(otherRegister.message, L10n.errorAccountCreationNotPossible, "The registration message should always be the same.") } } diff --git a/UnitTests/Sources/ServerConfirmationScreenViewModelTests.swift b/UnitTests/Sources/ServerConfirmationScreenViewModelTests.swift index c18cb2b2dd..0d89417d09 100644 --- a/UnitTests/Sources/ServerConfirmationScreenViewModelTests.swift +++ b/UnitTests/Sources/ServerConfirmationScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/ServerSelectionViewModelTests.swift b/UnitTests/Sources/ServerSelectionViewModelTests.swift index fb476f0023..b6aafa1a6d 100644 --- a/UnitTests/Sources/ServerSelectionViewModelTests.swift +++ b/UnitTests/Sources/ServerSelectionViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/SessionDirectoriesTests.swift b/UnitTests/Sources/SessionDirectoriesTests.swift new file mode 100644 index 0000000000..62db895c7a --- /dev/null +++ b/UnitTests/Sources/SessionDirectoriesTests.swift @@ -0,0 +1,122 @@ +// +// Copyright 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 + +class SessionDirectoriesTests: XCTestCase { + let fileManager = FileManager.default + + func testInitWithUserID() { + // Given only a user ID. + let userID = "@user:matrix.org" + + // When creating the session directories using this. + let sessionDirectories = SessionDirectories(userID: userID) + + // 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")) + } + + func testInitWithDataDirectory() { + // Given only a session directory without a caches directory. + let sessionDirectoryName = UUID().uuidString + let sessionDirectory = URL.applicationSupportBaseDirectory.appending(component: sessionDirectoryName) + + // When creating the session directories using this. + let sessionDirectories = SessionDirectories(dataDirectory: sessionDirectory) + + // 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)) + } + + func testPathOutput() { + // Given session directories created from paths with spaces in them. + let originalDataPath = "/Users/John Smith/Data" + let originalCachePath = "/Users/John Smith/Caches" + let dataDirectory = URL(filePath: originalDataPath) + let cacheDirectory = URL(filePath: originalCachePath) + let sessionDirectories = SessionDirectories(dataDirectory: dataDirectory, cacheDirectory: cacheDirectory) + + // When getting the paths from the session directories struct. + let returnedDataPath = sessionDirectories.dataPath + let returnedCachePath = sessionDirectories.cachePath + + // Then the paths should not be escaped. + XCTAssertEqual(returnedDataPath, originalDataPath) + XCTAssertEqual(returnedCachePath, originalCachePath) + } + + func testDeleteDirectories() throws { + // Given a new set of session directories. + let sessionDirectories = SessionDirectories() + try fileManager.createDirectory(at: sessionDirectories.dataDirectory, withIntermediateDirectories: true) + try fileManager.createDirectory(at: sessionDirectories.cacheDirectory, withIntermediateDirectories: true) + XCTAssertTrue(fileManager.directoryExists(at: sessionDirectories.dataDirectory)) + XCTAssertTrue(fileManager.directoryExists(at: sessionDirectories.cacheDirectory)) + + // When deleting the directories. + sessionDirectories.delete() + + // Then neither directory should exist on disk. + XCTAssertFalse(fileManager.directoryExists(at: sessionDirectories.dataDirectory)) + XCTAssertFalse(fileManager.directoryExists(at: sessionDirectories.cacheDirectory)) + } + + func testDeleteTransientUserData() throws { + // Given a set of session directories with some databases. + let sessionDirectories = SessionDirectories() + try fileManager.createDirectory(at: sessionDirectories.dataDirectory, withIntermediateDirectories: true) + try fileManager.createDirectory(at: sessionDirectories.cacheDirectory, withIntermediateDirectories: true) + XCTAssertTrue(fileManager.directoryExists(at: sessionDirectories.dataDirectory)) + XCTAssertTrue(fileManager.directoryExists(at: sessionDirectories.cacheDirectory)) + + sessionDirectories.generateMockData() + XCTAssertTrue(fileManager.fileExists(atPath: sessionDirectories.mockStateStorePath)) + XCTAssertTrue(fileManager.fileExists(atPath: sessionDirectories.mockCryptoStorePath)) + XCTAssertTrue(fileManager.fileExists(atPath: sessionDirectories.mockEventCachePath)) + XCTAssertEqual(try fileManager.numberOfItems(at: sessionDirectories.dataDirectory), 6) + XCTAssertEqual(try fileManager.numberOfItems(at: sessionDirectories.cacheDirectory), 3) + + // When deleting transient user data. + sessionDirectories.deleteTransientUserData() + + // Then the data directory should only contain the crypto store and the cache directory should remain but be empty. + XCTAssertTrue(fileManager.directoryExists(at: sessionDirectories.dataDirectory)) + XCTAssertEqual(try fileManager.numberOfItems(at: sessionDirectories.dataDirectory), 3) + XCTAssertFalse(fileManager.fileExists(atPath: sessionDirectories.mockStateStorePath)) + XCTAssertTrue(fileManager.fileExists(atPath: sessionDirectories.mockCryptoStorePath)) + + XCTAssertTrue(fileManager.directoryExists(at: sessionDirectories.cacheDirectory)) + XCTAssertEqual(try fileManager.numberOfItems(at: sessionDirectories.cacheDirectory), 0) + XCTAssertFalse(fileManager.fileExists(atPath: sessionDirectories.mockEventCachePath)) + + // The tests are done, tidy up these useless directories ๐Ÿงน + sessionDirectories.delete() + } +} + +private extension SessionDirectories { + var mockStateStorePath: String { dataDirectory.appending(component: "matrix-sdk-state.sqlite3").path(percentEncoded: false) } + var mockCryptoStorePath: String { dataDirectory.appending(component: "matrix-sdk-crypto.sqlite3").path(percentEncoded: false) } + var mockEventCachePath: String { cacheDirectory.appending(component: "matrix-sdk-event-cache.sqlite3").path(percentEncoded: false) } + + func generateMockData() { + generateMockDatabase(atPath: mockStateStorePath) + generateMockDatabase(atPath: mockCryptoStorePath) + generateMockDatabase(atPath: mockEventCachePath) + } + + private func generateMockDatabase(atPath path: String) { + FileManager.default.createFile(atPath: path, contents: nil) + FileManager.default.createFile(atPath: path + "-shm", contents: nil) + FileManager.default.createFile(atPath: path + "-wal", contents: nil) + } +} diff --git a/UnitTests/Sources/SessionVerificationStateMachineTests.swift b/UnitTests/Sources/SessionVerificationStateMachineTests.swift index 07b829b887..472c86549c 100644 --- a/UnitTests/Sources/SessionVerificationStateMachineTests.swift +++ b/UnitTests/Sources/SessionVerificationStateMachineTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/SessionVerificationViewModelTests.swift b/UnitTests/Sources/SessionVerificationViewModelTests.swift index 5ec7c4b213..c19c2df466 100644 --- a/UnitTests/Sources/SessionVerificationViewModelTests.swift +++ b/UnitTests/Sources/SessionVerificationViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/UnitTests/Sources/SettingsViewModelTests.swift b/UnitTests/Sources/SettingsViewModelTests.swift index f8a5b23cee..7d288bf097 100644 --- a/UnitTests/Sources/SettingsViewModelTests.swift +++ b/UnitTests/Sources/SettingsViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/UnitTests/Sources/SoftLogoutViewModelTests.swift b/UnitTests/Sources/SoftLogoutViewModelTests.swift index 4200c43511..ca5f3dfa69 100644 --- a/UnitTests/Sources/SoftLogoutViewModelTests.swift +++ b/UnitTests/Sources/SoftLogoutViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/StartChatViewModelTests.swift b/UnitTests/Sources/StartChatViewModelTests.swift index 01382b8eb5..678e697a72 100644 --- a/UnitTests/Sources/StartChatViewModelTests.swift +++ b/UnitTests/Sources/StartChatViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/StaticLocationScreenViewModelTests.swift b/UnitTests/Sources/StaticLocationScreenViewModelTests.swift index e70b1b8da3..6f699363e2 100644 --- a/UnitTests/Sources/StaticLocationScreenViewModelTests.swift +++ b/UnitTests/Sources/StaticLocationScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/UnitTests/Sources/StringTests.swift b/UnitTests/Sources/StringTests.swift index b6920fa51f..b77900b2ef 100644 --- a/UnitTests/Sources/StringTests.swift +++ b/UnitTests/Sources/StringTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/TextBasedRoomTimelineTests.swift b/UnitTests/Sources/TextBasedRoomTimelineTests.swift index 119543d311..775621fcbc 100644 --- a/UnitTests/Sources/TextBasedRoomTimelineTests.swift +++ b/UnitTests/Sources/TextBasedRoomTimelineTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @testable import ElementX @@ -70,7 +61,7 @@ final class TextBasedRoomTimelineTests: XCTestCase { sender: .init(id: UUID().uuidString), content: .init(body: "Test")) timelineItem.properties.isEdited = true - timelineItem.properties.deliveryStatus = .sendingFailed + timelineItem.properties.deliveryStatus = .sendingFailed(.unknown) let editedCount = L10n.commonEditedSuffix.count XCTAssertEqual(timelineItem.additionalWhitespaces(), timestamp.count + editedCount + 5) } diff --git a/UnitTests/Sources/TimelineItemFactoryTests.swift b/UnitTests/Sources/TimelineItemFactoryTests.swift index 9b75a6516a..ec352957e1 100644 --- a/UnitTests/Sources/TimelineItemFactoryTests.swift +++ b/UnitTests/Sources/TimelineItemFactoryTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2024 New Vector Ltd +// Copyright 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @testable import ElementX @@ -24,7 +15,6 @@ class TimelineItemFactoryTests: XCTestCase { let senderUserID = "@bob:matrix.org" let factory = RoomTimelineItemFactory(userID: ownUserID, - encryptionAuthenticityEnabled: true, attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), stateEventStringBuilder: RoomStateEventStringBuilder(userID: ownUserID)) diff --git a/UnitTests/Sources/TimelineViewModelTests.swift b/UnitTests/Sources/TimelineViewModelTests.swift new file mode 100644 index 0000000000..9876a7cad1 --- /dev/null +++ b/UnitTests/Sources/TimelineViewModelTests.swift @@ -0,0 +1,494 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +@testable import ElementX + +import Combine +import XCTest + +@MainActor +class TimelineViewModelTests: XCTestCase { + var userIndicatorControllerMock: UserIndicatorControllerMock! + var cancellables = Set() + + override func setUp() async throws { + AppSettings.resetAllSettings() + cancellables.removeAll() + userIndicatorControllerMock = UserIndicatorControllerMock.default + } + + override func tearDown() async throws { + userIndicatorControllerMock = nil + } + + // MARK: - Message Grouping + + func testMessageGrouping() { + // Given 3 messages from Bob. + let items = [ + TextRoomTimelineItem(text: "Message 1", + sender: "bob"), + TextRoomTimelineItem(text: "Message 2", + sender: "bob"), + TextRoomTimelineItem(text: "Message 3", + sender: "bob") + ] + + // When showing them in a timeline. + let timelineController = MockRoomTimelineController() + timelineController.timelineItems = items + let viewModel = makeViewModel(timelineController: timelineController) + + // Then the messages should be grouped together. + XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .first, "Nothing should prevent the first message from being grouped.") + XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[1].groupStyle, .middle, "Nothing should prevent the middle message from being grouped.") + XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[2].groupStyle, .last, "Nothing should prevent the last message from being grouped.") + } + + func testMessageGroupingMultipleSenders() { + // Given some interleaved messages from Bob and Alice. + let items = [ + TextRoomTimelineItem(text: "Message 1", + sender: "alice"), + TextRoomTimelineItem(text: "Message 2", + sender: "bob"), + TextRoomTimelineItem(text: "Message 3", + sender: "alice"), + TextRoomTimelineItem(text: "Message 4", + sender: "alice"), + TextRoomTimelineItem(text: "Message 5", + sender: "bob"), + TextRoomTimelineItem(text: "Message 6", + sender: "bob") + ] + + // When showing them in a timeline. + let timelineController = MockRoomTimelineController() + timelineController.timelineItems = items + let viewModel = makeViewModel(timelineController: timelineController) + + // Then the messages should be grouped by sender. + XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .single, "A message should not be grouped when the sender changes.") + XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[1].groupStyle, .single, "A message should not be grouped when the sender changes.") + XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[2].groupStyle, .first, "A group should start with a new sender if there are more messages from that sender.") + XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[3].groupStyle, .last, "A group should be ended when the sender changes in the next message.") + XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[4].groupStyle, .first, "A group should start with a new sender if there are more messages from that sender.") + XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[5].groupStyle, .last, "A group should be ended when the sender changes in the next message.") + } + + func testMessageGroupingWithLeadingReactions() { + // Given 3 messages from Bob where the first message has a reaction. + let items = [ + TextRoomTimelineItem(text: "Message 1", + sender: "bob", + addReactions: true), + TextRoomTimelineItem(text: "Message 2", + sender: "bob"), + TextRoomTimelineItem(text: "Message 3", + sender: "bob") + ] + + // When showing them in a timeline. + let timelineController = MockRoomTimelineController() + timelineController.timelineItems = items + let viewModel = makeViewModel(timelineController: timelineController) + + // Then the first message should not be grouped but the other two should. + XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .single, "When the first message has reactions it should not be grouped.") + XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[1].groupStyle, .first, "A new group should be made when the preceding message has reactions.") + XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[2].groupStyle, .last, "Nothing should prevent the last message from being grouped.") + } + + func testMessageGroupingWithInnerReactions() { + // Given 3 messages from Bob where the middle message has a reaction. + let items = [ + TextRoomTimelineItem(text: "Message 1", + sender: "bob"), + TextRoomTimelineItem(text: "Message 2", + sender: "bob", + addReactions: true), + TextRoomTimelineItem(text: "Message 3", + sender: "bob") + ] + + // When showing them in a timeline. + let timelineController = MockRoomTimelineController() + timelineController.timelineItems = items + let viewModel = makeViewModel(timelineController: timelineController) + + // Then the first and second messages should be grouped and the last one should not. + XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .first, "Nothing should prevent the first message from being grouped.") + XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[1].groupStyle, .last, "When the message has reactions, the group should end here.") + XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[2].groupStyle, .single, "The last message should not be grouped when the preceding message has reactions.") + } + + func testMessageGroupingWithTrailingReactions() { + // Given 3 messages from Bob where the last message has a reaction. + let items = [ + TextRoomTimelineItem(text: "Message 1", + sender: "bob"), + TextRoomTimelineItem(text: "Message 2", + sender: "bob"), + TextRoomTimelineItem(text: "Message 3", + sender: "bob", + addReactions: true) + ] + + // When showing them in a timeline. + let timelineController = MockRoomTimelineController() + timelineController.timelineItems = items + let viewModel = makeViewModel(timelineController: timelineController) + + // Then the messages should be grouped together. + XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .first, "Nothing should prevent the first message from being grouped.") + XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[1].groupStyle, .middle, "Nothing should prevent the second message from being grouped.") + XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[2].groupStyle, .last, "Reactions on the last message should not prevent it from being grouped.") + } + + // MARK: - Focussing + + func testFocusItem() async throws { + // Given a room with 3 items loaded in a live timeline. + let items = [TextRoomTimelineItem(eventID: "t1"), + TextRoomTimelineItem(eventID: "t2"), + TextRoomTimelineItem(eventID: "t3")] + let timelineController = MockRoomTimelineController() + timelineController.timelineItems = items + + let viewModel = makeViewModel(timelineController: timelineController) + XCTAssertEqual(timelineController.focusOnEventCallCount, 0) + XCTAssertTrue(viewModel.context.viewState.timelineViewState.isLive) + XCTAssertNil(viewModel.context.viewState.timelineViewState.focussedEvent) + + // When focussing on an item that isn't loaded. + let deferred = deferFulfillment(viewModel.context.$viewState) { !$0.timelineViewState.isLive } + await viewModel.focusOnEvent(eventID: "t4") + try await deferred.fulfill() + + // Then a new timeline should be loaded and the room focussed on that event. + XCTAssertEqual(timelineController.focusOnEventCallCount, 1) + XCTAssertFalse(viewModel.context.viewState.timelineViewState.isLive) + XCTAssertEqual(viewModel.context.viewState.timelineViewState.focussedEvent, .init(eventID: "t4", appearance: .immediate)) + } + + func testFocusLoadedItem() async throws { + // Given a room with 3 items loaded in a live timeline. + let items = [TextRoomTimelineItem(eventID: "t1"), + TextRoomTimelineItem(eventID: "t2"), + TextRoomTimelineItem(eventID: "t3")] + let timelineController = MockRoomTimelineController() + timelineController.timelineItems = items + + let viewModel = makeViewModel(timelineController: timelineController) + XCTAssertEqual(timelineController.focusOnEventCallCount, 0) + XCTAssertTrue(viewModel.context.viewState.timelineViewState.isLive) + XCTAssertNil(viewModel.context.viewState.timelineViewState.focussedEvent) + + // When focussing on a loaded item. + let deferred = deferFailure(viewModel.context.$viewState, timeout: 1) { !$0.timelineViewState.isLive } + await viewModel.focusOnEvent(eventID: "t1") + try await deferred.fulfill() + + // Then the timeline should remain live and the item should be focussed. + XCTAssertEqual(timelineController.focusOnEventCallCount, 0) + XCTAssertTrue(viewModel.context.viewState.timelineViewState.isLive) + XCTAssertEqual(viewModel.context.viewState.timelineViewState.focussedEvent, .init(eventID: "t1", appearance: .animated)) + } + + func testFocusLive() async throws { + // Given a room with a non-live timeline focussed on a particular event. + let items = [TextRoomTimelineItem(eventID: "t1"), + TextRoomTimelineItem(eventID: "t2"), + TextRoomTimelineItem(eventID: "t3")] + let timelineController = MockRoomTimelineController() + timelineController.timelineItems = items + + let viewModel = makeViewModel(timelineController: timelineController) + + var deferred = deferFulfillment(viewModel.context.$viewState) { !$0.timelineViewState.isLive } + await viewModel.focusOnEvent(eventID: "t4") + try await deferred.fulfill() + + XCTAssertEqual(timelineController.focusLiveCallCount, 0) + XCTAssertFalse(viewModel.context.viewState.timelineViewState.isLive) + XCTAssertEqual(viewModel.context.viewState.timelineViewState.focussedEvent, .init(eventID: "t4", appearance: .immediate)) + + // When switching back to a live timeline. + deferred = deferFulfillment(viewModel.context.$viewState) { $0.timelineViewState.isLive } + viewModel.context.send(viewAction: .focusLive) + try await deferred.fulfill() + + // Then the timeline should switch back to being live and the event focus should be removed. + XCTAssertEqual(timelineController.focusLiveCallCount, 1) + XCTAssertTrue(viewModel.context.viewState.timelineViewState.isLive) + XCTAssertNil(viewModel.context.viewState.timelineViewState.focussedEvent) + } + + func testInitialFocusViewState() async throws { + let timelineController = MockRoomTimelineController() + + let viewModel = makeViewModel(focussedEventID: "t10", timelineController: timelineController) + XCTAssertEqual(viewModel.context.viewState.timelineViewState.focussedEvent, .init(eventID: "t10", appearance: .immediate)) + } + + // MARK: - Read Receipts + + // swiftlint:disable force_unwrapping + func testSendReadReceipt() async throws { + // Given a room with only text items in the timeline + let items = [TextRoomTimelineItem(eventID: "t1"), + TextRoomTimelineItem(eventID: "t2"), + TextRoomTimelineItem(eventID: "t3")] + let (viewModel, _, timelineProxy, _) = readReceiptsConfiguration(with: items) + + // When sending a read receipt for the last item. + viewModel.context.send(viewAction: .sendReadReceiptIfNeeded(items.last!.id)) + try await Task.sleep(for: .milliseconds(100)) + + // Then the receipt should be sent. + XCTAssertEqual(timelineProxy.sendReadReceiptForTypeCalled, true) + let arguments = timelineProxy.sendReadReceiptForTypeReceivedArguments + XCTAssertEqual(arguments?.eventID, "t3") + XCTAssertEqual(arguments?.type, .read) + } + + func testSendMoreReadReceipts() async throws { + // Given a room with only text items in the timeline that are all read. + let items = [TextRoomTimelineItem(eventID: "t1"), + TextRoomTimelineItem(eventID: "t2"), + TextRoomTimelineItem(eventID: "t3")] + let (viewModel, _, timelineProxy, timelineController) = readReceiptsConfiguration(with: items) + viewModel.context.send(viewAction: .sendReadReceiptIfNeeded(items.last!.id)) + try await Task.sleep(for: .milliseconds(100)) + XCTAssertEqual(timelineProxy.sendReadReceiptForTypeCallsCount, 1) + var arguments = timelineProxy.sendReadReceiptForTypeReceivedArguments + XCTAssertEqual(arguments?.eventID, "t3") + XCTAssertEqual(arguments?.type, .read) + + // When sending a receipt for the first item in the timeline. + viewModel.context.send(viewAction: .sendReadReceiptIfNeeded(items.first!.id)) + try await Task.sleep(for: .milliseconds(100)) + + // When a new message is received and marked as read. + let newMessage = TextRoomTimelineItem(eventID: "t4") + timelineController.timelineItems.append(newMessage) + timelineController.callbacks.send(.updatedTimelineItems(timelineItems: timelineController.timelineItems, isSwitchingTimelines: false)) + try await Task.sleep(for: .milliseconds(100)) + + viewModel.context.send(viewAction: .sendReadReceiptIfNeeded(newMessage.id)) + try await Task.sleep(for: .milliseconds(100)) + + // Then the request should be made. + XCTAssertEqual(timelineProxy.sendReadReceiptForTypeCallsCount, 3) + arguments = timelineProxy.sendReadReceiptForTypeReceivedArguments + XCTAssertEqual(arguments?.eventID, "t4") + XCTAssertEqual(arguments?.type, .read) + } + + func testSendReadReceiptWithoutEvents() async throws { + // Given a room with only virtual items. + let items = [SeparatorRoomTimelineItem(timelineID: "v1"), + SeparatorRoomTimelineItem(timelineID: "v2"), + SeparatorRoomTimelineItem(timelineID: "v3")] + let (viewModel, _, timelineProxy, _) = readReceiptsConfiguration(with: items) + + // When sending a read receipt for the last item. + viewModel.context.send(viewAction: .sendReadReceiptIfNeeded(items.last!.id)) + try await Task.sleep(for: .milliseconds(100)) + + // Then nothing should be sent. + XCTAssertEqual(timelineProxy.sendReadReceiptForTypeCalled, false) + } + + func testSendReadReceiptVirtualLast() async throws { + // Given a room where the last event is a virtual item. + let items: [RoomTimelineItemProtocol] = [TextRoomTimelineItem(eventID: "t1"), + TextRoomTimelineItem(eventID: "t2"), + SeparatorRoomTimelineItem(timelineID: "v3")] + let (viewModel, _, _, _) = readReceiptsConfiguration(with: items) + + // When sending a read receipt for the last item. + viewModel.context.send(viewAction: .sendReadReceiptIfNeeded(items.last!.id)) + try await Task.sleep(for: .milliseconds(100)) + } + + // swiftlint:enable force_unwrapping + // swiftlint:disable:next large_tuple + private func readReceiptsConfiguration(with items: [RoomTimelineItemProtocol]) -> (TimelineViewModel, + JoinedRoomProxyMock, + TimelineProxyMock, + MockRoomTimelineController) { + let roomProxy = JoinedRoomProxyMock(.init(name: "")) + + let timelineProxy = TimelineProxyMock() + + roomProxy.timeline = timelineProxy + let timelineController = MockRoomTimelineController() + + timelineProxy.sendReadReceiptForTypeReturnValue = .success(()) + + timelineController.timelineItems = items + timelineController.roomProxy = roomProxy + + let viewModel = TimelineViewModel(roomProxy: roomProxy, + timelineController: timelineController, + mediaProvider: MockMediaProvider(), + mediaPlayerProvider: MediaPlayerProviderMock(), + voiceMessageMediaManager: VoiceMessageMediaManagerMock(), + userIndicatorController: userIndicatorControllerMock, + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) + return (viewModel, roomProxy, timelineProxy, timelineController) + } + + func testShowReadReceipts() async throws { + let receipts: [ReadReceipt] = [.init(userID: "@alice:matrix.org", formattedTimestamp: "12:00"), + .init(userID: "@charlie:matrix.org", formattedTimestamp: "11:00")] + // Given 3 messages from Bob where the middle message has a reaction. + let message = TextRoomTimelineItem(text: "Test", + sender: "bob", + addReadReceipts: receipts) + let id = message.id + + // When showing them in a timeline. + let timelineController = MockRoomTimelineController() + timelineController.timelineItems = [message] + let viewModel = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "", members: [RoomMemberProxyMock.mockAlice, RoomMemberProxyMock.mockCharlie])), + timelineController: timelineController, + mediaProvider: MockMediaProvider(), + mediaPlayerProvider: MediaPlayerProviderMock(), + voiceMessageMediaManager: VoiceMessageMediaManagerMock(), + userIndicatorController: userIndicatorControllerMock, + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) + + let deferred = deferFulfillment(viewModel.context.$viewState) { value in + value.bindings.readReceiptsSummaryInfo?.orderedReceipts == receipts + } + + viewModel.context.send(viewAction: .displayReadReceipts(itemID: id)) + try await deferred.fulfill() + } + + // MARK: - Pins + + func testPinnedEvents() async throws { + ServiceLocator.shared.settings.pinningEnabled = true + + // Note: We need to start the test with a non-default value so we know the view model has finished the Task. + let roomProxyMock = JoinedRoomProxyMock(.init(name: "", + pinnedEventIDs: .init(["test1"]))) + let actionsSubject = PassthroughSubject() + roomProxyMock.underlyingActionsPublisher = actionsSubject.eraseToAnyPublisher() + + let viewModel = TimelineViewModel(roomProxy: roomProxyMock, + timelineController: MockRoomTimelineController(), + mediaProvider: MockMediaProvider(), + mediaPlayerProvider: MediaPlayerProviderMock(), + voiceMessageMediaManager: VoiceMessageMediaManagerMock(), + userIndicatorController: userIndicatorControllerMock, + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) + + var deferred = deferFulfillment(viewModel.context.$viewState) { value in + value.pinnedEventIDs == ["test1"] + } + try await deferred.fulfill() + + roomProxyMock.underlyingPinnedEventIDs = ["test1", "test2"] + deferred = deferFulfillment(viewModel.context.$viewState) { value in + value.pinnedEventIDs == ["test1", "test2"] + } + actionsSubject.send(.roomInfoUpdate) + try await deferred.fulfill() + } + + func testCanUserPinEvents() async throws { + ServiceLocator.shared.settings.pinningEnabled = true + + // Note: We need to start the test with the non-default value so we know the view model has finished the Task. + let roomProxyMock = JoinedRoomProxyMock(.init(name: "", canUserPin: true)) + let actionsSubject = PassthroughSubject() + roomProxyMock.underlyingActionsPublisher = actionsSubject.eraseToAnyPublisher() + + let viewModel = TimelineViewModel(roomProxy: roomProxyMock, + timelineController: MockRoomTimelineController(), + mediaProvider: MockMediaProvider(), + mediaPlayerProvider: MediaPlayerProviderMock(), + voiceMessageMediaManager: VoiceMessageMediaManagerMock(), + userIndicatorController: userIndicatorControllerMock, + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) + + var deferred = deferFulfillment(viewModel.context.$viewState) { value in + value.canCurrentUserPin + } + try await deferred.fulfill() + + roomProxyMock.canUserPinOrUnpinUserIDReturnValue = .success(false) + deferred = deferFulfillment(viewModel.context.$viewState) { value in + !value.canCurrentUserPin + } + actionsSubject.send(.roomInfoUpdate) + try await deferred.fulfill() + } + + // MARK: - Helpers + + private func makeViewModel(roomProxy: JoinedRoomProxyProtocol? = nil, + focussedEventID: String? = nil, + timelineController: RoomTimelineControllerProtocol) -> TimelineViewModel { + TimelineViewModel(roomProxy: roomProxy ?? JoinedRoomProxyMock(.init(name: "")), + focussedEventID: focussedEventID, + timelineController: timelineController, + mediaProvider: MockMediaProvider(), + mediaPlayerProvider: MediaPlayerProviderMock(), + voiceMessageMediaManager: VoiceMessageMediaManagerMock(), + userIndicatorController: userIndicatorControllerMock, + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics) + } +} + +private extension TextRoomTimelineItem { + init(text: String, sender: String, addReactions: Bool = false, addReadReceipts: [ReadReceipt] = []) { + let reactions = addReactions ? [AggregatedReaction(accountOwnerID: "bob", key: "๐Ÿฆ„", senders: [ReactionSender(id: sender, timestamp: Date())])] : [] + self.init(id: .random, + timestamp: "10:47 am", + isOutgoing: sender == "bob", + isEditable: sender == "bob", + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "@\(sender):server.com", displayName: sender), + content: .init(body: text), + properties: RoomTimelineItemProperties(reactions: reactions, orderedReadReceipts: addReadReceipts)) + } +} + +private extension SeparatorRoomTimelineItem { + init(timelineID: String) { + self.init(id: .init(timelineID: timelineID), text: "") + } +} + +private extension TextRoomTimelineItem { + init(eventID: String) { + self.init(id: .init(timelineID: UUID().uuidString, eventID: eventID), + timestamp: "", + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: ""), + content: .init(body: "Hello, World!")) + } +} diff --git a/UnitTests/Sources/TracingConfigurationTests.swift b/UnitTests/Sources/TracingConfigurationTests.swift index efe7827d3c..864c8898fe 100644 --- a/UnitTests/Sources/TracingConfigurationTests.swift +++ b/UnitTests/Sources/TracingConfigurationTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/URLComponentsTests.swift b/UnitTests/Sources/URLComponentsTests.swift index 7403da1c0f..9c64577b5e 100644 --- a/UnitTests/Sources/URLComponentsTests.swift +++ b/UnitTests/Sources/URLComponentsTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/UserAgentBuilderTests.swift b/UnitTests/Sources/UserAgentBuilderTests.swift index 3cb3100b8a..1c88fa032a 100644 --- a/UnitTests/Sources/UserAgentBuilderTests.swift +++ b/UnitTests/Sources/UserAgentBuilderTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/UserDiscoveryService/UserDiscoveryServiceTest.swift b/UnitTests/Sources/UserDiscoveryService/UserDiscoveryServiceTest.swift index 2bf7724420..85fa2d51ae 100644 --- a/UnitTests/Sources/UserDiscoveryService/UserDiscoveryServiceTest.swift +++ b/UnitTests/Sources/UserDiscoveryService/UserDiscoveryServiceTest.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/UserIndicatorControllerTests.swift b/UnitTests/Sources/UserIndicatorControllerTests.swift index 599a31d31d..f69c6acf88 100644 --- a/UnitTests/Sources/UserIndicatorControllerTests.swift +++ b/UnitTests/Sources/UserIndicatorControllerTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Foundation diff --git a/UnitTests/Sources/UserPreferenceTests.swift b/UnitTests/Sources/UserPreferenceTests.swift index 15599debbe..f9873b4455 100644 --- a/UnitTests/Sources/UserPreferenceTests.swift +++ b/UnitTests/Sources/UserPreferenceTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // @testable import ElementX diff --git a/UnitTests/Sources/UserProfileScreenViewModelTests.swift b/UnitTests/Sources/UserProfileScreenViewModelTests.swift index 7003ee8143..ecd4d2efda 100644 --- a/UnitTests/Sources/UserProfileScreenViewModelTests.swift +++ b/UnitTests/Sources/UserProfileScreenViewModelTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/UserSession/UserSessionTests.swift b/UnitTests/Sources/UserSession/UserSessionTests.swift index 922c8f350b..f10a4f8da8 100644 --- a/UnitTests/Sources/UserSession/UserSessionTests.swift +++ b/UnitTests/Sources/UserSession/UserSessionTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2022 New Vector Ltd +// Copyright 2022-2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @testable import ElementX diff --git a/UnitTests/Sources/UserSessionFlowCoordinatorTests.swift b/UnitTests/Sources/UserSessionFlowCoordinatorTests.swift index 240f2adb55..24e482b76e 100644 --- a/UnitTests/Sources/UserSessionFlowCoordinatorTests.swift +++ b/UnitTests/Sources/UserSessionFlowCoordinatorTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import XCTest diff --git a/UnitTests/Sources/VoiceMessageCacheTests.swift b/UnitTests/Sources/VoiceMessageCacheTests.swift index be57a32dca..12f8681486 100644 --- a/UnitTests/Sources/VoiceMessageCacheTests.swift +++ b/UnitTests/Sources/VoiceMessageCacheTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/UnitTests/Sources/VoiceMessageMediaManagerTests.swift b/UnitTests/Sources/VoiceMessageMediaManagerTests.swift index 0ba81a31ac..644bdd62ea 100644 --- a/UnitTests/Sources/VoiceMessageMediaManagerTests.swift +++ b/UnitTests/Sources/VoiceMessageMediaManagerTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine diff --git a/UnitTests/Sources/VoiceMessageRecorderTests.swift b/UnitTests/Sources/VoiceMessageRecorderTests.swift index e9408bc185..bba8e525fb 100644 --- a/UnitTests/Sources/VoiceMessageRecorderTests.swift +++ b/UnitTests/Sources/VoiceMessageRecorderTests.swift @@ -1,17 +1,8 @@ // -// Copyright 2023 New Vector Ltd +// Copyright 2023, 2024 New Vector Ltd. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. // import Combine @@ -204,7 +195,7 @@ class VoiceMessageRecorderTests: XCTestCase { } func testSendVoiceMessage_NoRecordingFile() async throws { - let roomProxy = RoomProxyMock() + let roomProxy = JoinedRoomProxyMock() // If there is no recording file, an error is expected audioRecorder.audioFileURL = nil @@ -219,7 +210,7 @@ class VoiceMessageRecorderTests: XCTestCase { // If the converter returns an error audioConverter.convertToOpusOggSourceURLDestinationURLThrowableError = AudioConverterError.conversionFailed(nil) - let roomProxy = RoomProxyMock() + let roomProxy = JoinedRoomProxyMock() guard case .failure(.failedSendingVoiceMessage) = await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy, audioConverter: audioConverter) else { XCTFail("An error is expected") return @@ -237,7 +228,7 @@ class VoiceMessageRecorderTests: XCTestCase { } let timelineProxy = TimelineProxyMock() - let roomProxy = RoomProxyMock() + let roomProxy = JoinedRoomProxyMock() roomProxy.timeline = timelineProxy timelineProxy.sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleReturnValue = .failure(.sdkError(SDKError.generic)) guard case .failure(.failedSendingVoiceMessage) = await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy, audioConverter: audioConverter) else { @@ -258,7 +249,7 @@ class VoiceMessageRecorderTests: XCTestCase { } let timelineProxy = TimelineProxyMock() - let roomProxy = RoomProxyMock() + let roomProxy = JoinedRoomProxyMock() roomProxy.timeline = timelineProxy timelineProxy.sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleReturnValue = .failure(.sdkError(SDKError.generic)) guard case .failure(.failedSendingVoiceMessage) = await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy, audioConverter: audioConverter) else { @@ -281,7 +272,7 @@ class VoiceMessageRecorderTests: XCTestCase { // If the media upload fails let timelineProxy = TimelineProxyMock() - let roomProxy = RoomProxyMock() + let roomProxy = JoinedRoomProxyMock() roomProxy.timeline = timelineProxy timelineProxy.sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleReturnValue = .failure(.sdkError(SDKError.generic)) guard case .failure(.failedSendingVoiceMessage) = await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy, audioConverter: audioConverter) else { @@ -297,7 +288,7 @@ class VoiceMessageRecorderTests: XCTestCase { } let timelineProxy = TimelineProxyMock() - let roomProxy = RoomProxyMock() + let roomProxy = JoinedRoomProxyMock() roomProxy.timeline = timelineProxy audioRecorder.currentTime = 42 audioRecorder.audioFileURL = imageFileURL diff --git a/UnitTests/Sources/WaitlistScreenViewModelTests.swift b/UnitTests/Sources/WaitlistScreenViewModelTests.swift deleted file mode 100644 index 12491e4163..0000000000 --- a/UnitTests/Sources/WaitlistScreenViewModelTests.swift +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import XCTest - -@testable import ElementX - -@MainActor -class WaitlistScreenViewModelTests: XCTestCase { - var viewModel: WaitlistScreenViewModelProtocol! - var context: WaitlistScreenViewModelType.Context { viewModel.context } - - override func setUpWithError() throws { - viewModel = WaitlistScreenViewModel(homeserver: .mockMatrixDotOrg) - } - - func testSuccess() async throws { - XCTAssertNil(context.viewState.userSession, "No user session should be set on a new view model.") - XCTAssertTrue(context.viewState.isWaiting, "The view should start off in the waiting state.") - - viewModel.update(userSession: UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "@alice:matrix.org"))))) - - XCTAssertNotNil(context.viewState.userSession, "The user session should have been updated.") - XCTAssertFalse(context.viewState.isWaiting, "The view should not be in the waiting state after setting a user session.") - } -} diff --git a/ci_scripts/free_space.sh b/ci_scripts/free_space.sh new file mode 100755 index 0000000000..18fdcc3351 --- /dev/null +++ b/ci_scripts/free_space.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +# +# Taken from +# https://github.com/actions/runner-images/issues/2840#issuecomment-790492173 +# + +set -ux + +df -h +sudo rm -rf /usr/share/dotnet +sudo rm -rf /opt/ghc +sudo rm -rf "/usr/local/share/boost" +sudo rm -rf "$AGENT_TOOLSDIRECTORY" +df -h diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 5b46fd1f0d..d6b573b818 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -7,7 +7,7 @@ if File.exist?(enterprise) end before_all do - xcversion(version: "15.4") + xcversion(version: "16.0") ENV["FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT"] = "180" ENV["FASTLANE_XCODE_LIST_TIMEOUT"] = "180" @@ -82,7 +82,7 @@ end lane :unit_tests do |options| run_tests( scheme: "UnitTests", - device: 'iPhone 15', + device: 'iPhone 16', ensure_devices_found: true, result_bundle: true, number_of_retries: 3, @@ -95,7 +95,6 @@ lane :unit_tests do |options| ensure_devices_found: true, result_bundle: true, number_of_retries: 3, - xcargs: '-skipPackagePluginValidation', ) end @@ -104,18 +103,19 @@ end lane :ui_tests do |options| # Use a fresh simulator state to ensure hardware keyboard isn't attached. - reset_simulator_contents() + # Not necessary when running on GitHub. + # reset_simulator_contents() create_simulator_if_necessary( - name: "iPhone 15", - type: "com.apple.CoreSimulator.SimDeviceType.iPhone-15", - runtime: "com.apple.CoreSimulator.SimRuntime.iOS-17-5" + name: "iPhone 16", + type: "com.apple.CoreSimulator.SimDeviceType.iPhone-16", + runtime: "com.apple.CoreSimulator.SimRuntime.iOS-18-0" ) create_simulator_if_necessary( name: "iPad (10th generation)", type: "com.apple.CoreSimulator.SimDeviceType.iPad-10th-generation", - runtime: "com.apple.CoreSimulator.SimRuntime.iOS-17-5" + runtime: "com.apple.CoreSimulator.SimRuntime.iOS-18-0" ) if options[:test_name] @@ -126,7 +126,7 @@ lane :ui_tests do |options| run_tests( scheme: "UITests", - devices: ["iPhone 15", "iPad (10th generation)"], + devices: ["iPhone 16", "iPad (10th generation)"], ensure_devices_found: true, prelaunch_simulator: true, result_bundle: true, @@ -140,14 +140,14 @@ lane :integration_tests do clear_derived_data() create_simulator_if_necessary( - name: "iPhone 15 Pro", - type: "com.apple.CoreSimulator.SimDeviceType.iPhone-15-Pro", - runtime: "com.apple.CoreSimulator.SimRuntime.iOS-17-5" + name: "iPhone 16 Pro", + type: "com.apple.CoreSimulator.SimDeviceType.iPhone-16-Pro", + runtime: "com.apple.CoreSimulator.SimRuntime.iOS-18-0" ) run_tests( scheme: "IntegrationTests", - devices: ["iPhone 15 Pro"], + devices: ["iPhone 16 Pro"], ensure_devices_found: true, result_bundle: true, reset_simulator: true diff --git a/project-tchap-x.yml b/project-tchap-x.yml index c330ddd83b..d5ae1e0c55 100644 --- a/project-tchap-x.yml +++ b/project-tchap-x.yml @@ -23,14 +23,14 @@ options: settings: DEVELOPMENT_TEAM: NVMQD635C6 - MARKETING_VERSION: 1.8.0 + MARKETING_VERSION: 0.1.1 CURRENT_PROJECT_VERSION: 1 include: - path: project.yml -- path: TchapX/production/SupportingFiles/target.yml +- path: TchapX/SupportingFiles/target-production.yml - path: TchapX/production/SupportingFiles/NSE/target.yml -- path: TchapX/staging/SupportingFiles/target.yml +- path: TchapX/SupportingFiles/target-staging.yml - path: TchapX/staging/SupportingFiles/NSE/target.yml -- path: TchapX/development/SupportingFiles/target.yml +- path: TchapX/SupportingFiles/target-development.yml - path: TchapX/development/SupportingFiles/NSE/target.yml diff --git a/project.yml b/project.yml index 484416459b..04567db8db 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.7.3 + MARKETING_VERSION: 1.8.4 CURRENT_PROJECT_VERSION: 1 SUPPORTS_MACCATALYST: false @@ -60,15 +60,15 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/element-hq/matrix-rust-components-swift - exactVersion: 1.0.36 + exactVersion: 1.0.52 # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios - revision: ab79d0cc5e5bb2ef3624b76c99471e414c12e8da + revision: 92110afc158ac6ee7c68d5e975144bafa6c58396 # path: ../compound-ios AnalyticsEvents: url: https://github.com/matrix-org/matrix-analytics-events - minorVersion: 0.23.1 + minorVersion: 0.25.0 # path: ../matrix-analytics-events Emojibase: url: https://github.com/matrix-org/emojibase-bindings @@ -122,15 +122,12 @@ packages: PostHog: url: https://github.com/PostHog/posthog-ios minorVersion: 3.2.5 - Prefire: - url: https://github.com/BarredEwe/Prefire - minorVersion: 2.8.0 Sentry: url: https://github.com/getsentry/sentry-cocoa minorVersion: 8.30.0 SnapshotTesting: url: https://github.com/pointfreeco/swift-snapshot-testing - minorVersion: 1.17.2 + minorVersion: 1.17.5 SwiftState: url: https://github.com/ReactKit/SwiftState minorVersion: 6.0.0 diff --git a/tchapx-project.yml b/tchapx-project.yml deleted file mode 100644 index df795ec314..0000000000 --- a/tchapx-project.yml +++ /dev/null @@ -1,36 +0,0 @@ ---- -name: TchapX -attributes: - ORGANIZATIONNAME: Tchap - -fileGroups: -- tchapx-project.yml - -options: - groupOrdering:REPLACE: - - order: - - TchapX - - ElementX - - UnitTests - - UITests - - IntegrationTests - - Tools - - pattern: TchapX - order: - - Sources - - Resources - - SupportingFiles - -settings: - DEVELOPMENT_TEAM: NVMQD635C6 - MARKETING_VERSION: 1.8.0 - CURRENT_PROJECT_VERSION: 1 - -include: -- path: project.yml -- path: TchapX/production/SupportingFiles/target.yml -- path: TchapX/production/SupportingFiles/NSE/target.yml -- path: TchapX/staging/SupportingFiles/target.yml -- path: TchapX/staging/SupportingFiles/NSE/target.yml -- path: TchapX/development/SupportingFiles/target.yml -- path: TchapX/development/SupportingFiles/NSE/target.yml