diff --git a/CHANGES.md b/CHANGES.md index d2e289625..25f3abef4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,39 @@ +## Changes in 1.11.1 (2023-08-29) + +✨ Features + +- New settings cell to manage your account through MAS if the home server allows it. ([#7653](https://github.com/vector-im/element-ios/issues/7653)) + +🙌 Improvements + +- Upgrade MatrixSDK version ([v0.27.1](https://github.com/matrix-org/matrix-ios-sdk/releases/tag/v0.27.1)). + +🐛 Bugfixes + +- Prevent mention crashes when room members are missing display names (objc interop) ([#7649](https://github.com/vector-im/element-ios/pull/7649)) +- Add email UI is hidden if the 3 pid changes capability is disabled. ([#7645](https://github.com/vector-im/element-ios/issues/7645)) +- You can now log out from other sessions using MAS on supported OIDC home servers. ([#7646](https://github.com/vector-im/element-ios/issues/7646)) +- Deactivate account is hidden for servers with OIDC auth. ([#7648](https://github.com/vector-im/element-ios/issues/7648)) +- Prevent pill crashes when room members are missing display names (objc interop) ([#7651](https://github.com/vector-im/element-ios/issues/7651)) + + +## Changes in 1.11.0 (2023-08-15) + +✨ Features + +- Integrate Device Dehydration v2 through the Crypto SDK ([#7630](https://github.com/vector-im/element-ios/pull/7630)) + +🙌 Improvements + +- Upgrade MatrixSDK version ([v0.27.0](https://github.com/matrix-org/matrix-ios-sdk/releases/tag/v0.27.0)). +- Disable Siri, Share and Reply (from NSE) Extensions. ([#7618](https://github.com/vector-im/element-ios/issues/7618)) + +🐛 Bugfixes + +- Fix bug in SSO URL generation that was non-compliant with the spec. ([#7639](https://github.com/vector-im/element-ios/pull/7639)) +- Fix a crash when opening v11 rooms. ([#7633](https://github.com/vector-im/element-ios/issues/7633)) + + ## Changes in 1.10.14 (2023-06-21) 🙌 Improvements diff --git a/CHANGES_BWI.md b/CHANGES_BWI.md index 80278a54c..6dafe3ae9 100644 --- a/CHANGES_BWI.md +++ b/CHANGES_BWI.md @@ -1,3 +1,37 @@ +Changes in BWI project 2.10.0 (2023-09-26) +=================================================== + +Upstream merge ✨: +- v1.11.1 + +Features ✨: +- New WYSIWYG composer (#4941) + +Improvements 🙌: +- UI optimization room overview (#4704, #4806) +- Change date format for poll details (#4798) +- Add additional information to the developer menu for Beta app (#4565) +- Update huddle permissions for new rooms (#4928) +- Update element call permissions when resetting room permissions (#5035) +- Disable all WYSIWYG commands (#4955) +- Change date format for maintenance to ISO-8601 (#5071) +- Update notes room layout in room overview (#4802) +- Enable/disable notes room in settings (#4730) + +Bugfix 🐛: +- Crashfix for dm creation when WYSIWYG composer is enabled (#5133) +- Change permalink URL scheme (#4910) +- No popup for successful password change (#4951) + +Translations 🗣 : +- German translations voice message (#5017) +- German translations wrong password (#4857) +- Add special characters for password creation/resetting (#4952) + +SDK API changes ⚠️: + +Build 🧱: + Changes in BWI project 2.9.1 (2023-09-08) =================================================== diff --git a/Config/AppConfiguration.swift b/Config/AppConfiguration.swift index 2686a6048..4222295bc 100644 --- a/Config/AppConfiguration.swift +++ b/Config/AppConfiguration.swift @@ -55,6 +55,10 @@ class AppConfiguration: CommonConfiguration { // bwi: explicitly set option for key sharing MXSDKOptions.sharedInstance().enableRoomSharedHistoryOnInvite = BWIBuildSettings.shared.allowKeySharingOnRoomInvite + + // bwi: #4941 activate WYSIWYG and deactivate voice broadcast + RiotSettings.shared.enableWysiwygComposer = BWIBuildSettings.shared.enableFeatureWYSIWYGByDefault + RiotSettings.shared.enableVoiceBroadcast = BWIBuildSettings.shared.enableFeatureVoiceBroadcastsByDefault } diff --git a/Config/AppVersion.xcconfig b/Config/AppVersion.xcconfig index 92b5127ef..dcbbb154e 100644 --- a/Config/AppVersion.xcconfig +++ b/Config/AppVersion.xcconfig @@ -16,5 +16,5 @@ // // Version -MARKETING_VERSION = 2.9.1 +MARKETING_VERSION = 2.10.0 CURRENT_PROJECT_VERSION = 20220714163152 diff --git a/Config/BWIBuildSettings.swift b/Config/BWIBuildSettings.swift index 55ec0a76a..7a0669446 100644 --- a/Config/BWIBuildSettings.swift +++ b/Config/BWIBuildSettings.swift @@ -136,7 +136,6 @@ class BWIBuildSettings: NSObject { var bwiAutoCreateAliasOnRoomCreation = true var bwiLocationShareButtonVisible = false - var bwiUseCustomPersonalNotesAvatar = true var bwiBetterIgnoredUsers = true var bwiSettingsShowInAppNotifications = false var bwiFilteredContextMenu = true @@ -271,6 +270,9 @@ class BWIBuildSettings: NSObject { var applicationTermsConditionsUrlString = "" var applicationPrivacyPolicyWithMatomoSectionUrlString = "https://messenger.bwi.de/datenschutz#c6637" + // (#4751) use privacy policy link of well known + var bwiUseWellKnownPrivacyPolicyLink: Bool = false + // MARk: - Matrix permalinks // Paths for URLs that will considered as Matrix permalinks. Those permalinks are opened within the app var permalinkSupportedHosts: [String: [String]] = [:] @@ -509,7 +511,7 @@ class BWIBuildSettings: NSObject { var passwordIndicatorOnLogin = true // MARK: Displays the element base version on the settings screen - var elementBaseVersion = "1.10.14" + var elementBaseVersion = "1.11.1" var showElementBaseVersion = true @@ -530,6 +532,9 @@ class BWIBuildSettings: NSObject { var bwiPersonalNotesRoom = false var bwiPersonalNotesRoomLeavable = false var bwiResetPersonalNotesAccountData = false + var bwiUseCustomPersonalNotesAvatar = true + var bwiPersonalNotesVisibilityInSettings = false + var bwiShowTimelineSettings = false // MARK BWI personal state @@ -653,12 +658,30 @@ class BWIBuildSettings: NSObject { var accessibilityDeclarationFileEn = "" // MARK: Voice Broadcast - var enableLabFeatureVoiceBroadcasts = false + var enableFeatureVoiceBroadcastsByDefault = false // MARK: WYSIWYG - var enableLabFeatureWYSIWYG = false + var enableFeatureWYSIWYGByDefault = true + var enableWYSIWYGCommands = false // MARK: itunes var itunesAppLink = "" + + // MARK: itunes + var showAllChatsFilterMenu = false + + // MARK: itunes + var roomFiltersToggle = true + // MARK: OIDC + var isOIDCEnabled = true + + // MARK: Change Password + var showPasswordChangedConfirmation = true + + // MARK: Create Room Menu + var enableAllChatsToolbar = false + + // MARK: App Config + var avoidServerSelectionOnAppConfig = false } diff --git a/Config/BuM-Beta/BWIBuildSettings+BuM-Beta.swift b/Config/BuM-Beta/BWIBuildSettings+BuM-Beta.swift index 023974a5f..bb6112246 100644 --- a/Config/BuM-Beta/BWIBuildSettings+BuM-Beta.swift +++ b/Config/BuM-Beta/BWIBuildSettings+BuM-Beta.swift @@ -34,13 +34,12 @@ extension BWIBuildSettings { bwiLoginFlowLayout = false useRustEncryption = true bwiNotificationTimes = true - enableLabFeatureVoiceBroadcasts = true enableNewSessionManagerByDefault = true - enableLabFeatureWYSIWYG = true showMaintenanceInfoMessageType = true ignoreBlockingMaintenance = true - + bwiUseWellKnownPrivacyPolicyLink = true + itunesAppLink = "itms://itunes.apple.com/app/bundesmessenger-beta/id1617068656?mt=8" + avoidServerSelectionOnAppConfig = true } - } diff --git a/Config/BuM-Open/BWIBuildSettings+BuM-Open.swift b/Config/BuM-Open/BWIBuildSettings+BuM-Open.swift index 7ff2e64bc..ad899f84f 100644 --- a/Config/BuM-Open/BWIBuildSettings+BuM-Open.swift +++ b/Config/BuM-Open/BWIBuildSettings+BuM-Open.swift @@ -31,6 +31,7 @@ extension BWIBuildSettings { bwiEnableLoginProtection = false itunesAppLink = "itms://itunes.apple.com/app/bundesmessenger-open/id6450672686?mt=8" + avoidServerSelectionOnAppConfig = true } } diff --git a/Config/BuM/BWIBuildSettings+BuM.swift b/Config/BuM/BWIBuildSettings+BuM.swift index 1605a0865..2314716cf 100644 --- a/Config/BuM/BWIBuildSettings+BuM.swift +++ b/Config/BuM/BWIBuildSettings+BuM.swift @@ -27,7 +27,9 @@ extension BWIBuildSettings { authScreenShowTestServerOptions = false bwiNotificationTimes = true enableNewSessionManagerByDefault = true + bwiUseWellKnownPrivacyPolicyLink = true itunesAppLink = "itms://itunes.apple.com/app/bundesmessenger/id1616866351?mt=8" + avoidServerSelectionOnAppConfig = true } } diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index 44c008e0b..417da0c49 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -192,7 +192,7 @@ final class BuildSettings: NSObject { #else /// The configuration to use for analytics. Set `isEnabled` to false to disable analytics. static let analyticsConfiguration = AnalyticsConfiguration(isEnabled: BuildSettings.baseBundleIdentifier.starts(with: "im.vector.app"), - host: "https://posthog.hss.element.io", + host: "https://posthog.element.io", apiKey: "phc_Jzsm6DTm6V2705zeU5dcNvQDlonOR68XvX2sh1sEOHO", termsURL: URL(string: "https://element.io/cookie-policy")!) #endif diff --git a/Config/nexus_upload.sh b/Config/nexus_upload.sh index 376ca71a0..cb997e836 100755 --- a/Config/nexus_upload.sh +++ b/Config/nexus_upload.sh @@ -10,11 +10,25 @@ SUBDIR=$7 echo "params: $NEXUS_BASE_URL $VARIANT $EXT $VERSION $DATE_STR $GITHASH $SUBDIR" echo "dir: $PWD" +check_last_exit_code () { + if [ $1 -ne 0 ]; then + echo "Error: exit code != 0" + exit $1 + fi +} + +echo "checking if file is found" +find ../out$SUBDIR -name "*$VARIANT*.$EXT" | grep . +check_last_exit_code $? +echo "find end" + find ../out$SUBDIR -name "*$VARIANT*.$EXT" -print0 | while read -d $'\0' file do echo "Source: $file" zip -r $file.zip $file BASENAME=$(basename $file .zip)-$VERSION-$DATE_STR-$GITHASH.$EXT$SUBDIR.zip echo "Destination $NEXUS_BASE_URL/$VERSION/$BASENAME" - curl --fail -u $S_BWMESSENGER_ID:$S_BWMESSENGER_PASSWORD -v --upload-file $file.zip $NEXUS_BASE_URL/$VERSION/$BASENAME -done \ No newline at end of file + curl --fail -v -u $S_BWMESSENGER_ID:$S_BWMESSENGER_PASSWORD --upload-file $file.zip $NEXUS_BASE_URL/$VERSION/$BASENAME + check_last_exit_code $? +done +check_last_exit_code $? diff --git a/Podfile b/Podfile index 5ad00a6d9..6ae6b8b40 100644 --- a/Podfile +++ b/Podfile @@ -16,7 +16,7 @@ use_frameworks! # - `{ :specHash => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for MatrixSDK repo. Used by Fastfile during CI # # Warning: our internal tooling depends on the name of this variable name, so be sure not to change it -$matrixSDKVersion = '= 0.26.12' +$matrixSDKVersion = '= 0.27.1' # $matrixSDKVersion = :local # $matrixSDKVersion = { :branch => 'develop'} # $matrixSDKVersion = { :specHash => { git: 'https://git.io/fork123', branch: 'fix' } } @@ -43,7 +43,7 @@ when String # specific MatrixSDK released version $matrixSDKVersionSpec = $matrixSDKVersion end -$matrixSDKVersionSpec = { :git => 'https://dl-gitlab.example.com/bwmessenger/bundesmessenger/bundesmessenger-ios-sdk', :tag => 'v2.9.0' } +$matrixSDKVersionSpec = { :git => 'https://dl-gitlab.example.com/bwmessenger/bundesmessenger/bundesmessenger-ios-sdk', :tag => 'v2.10.0' } # Method to import the MatrixSDK def import_MatrixSDK @@ -178,11 +178,11 @@ abstract_target 'RiotPods' do target "RiotSwiftUI" do import_SwiftUI_pods - end + end target "RiotSwiftUITests" do import_SwiftUI_pods - end + end target "RiotNSE" do import_MatrixSDK @@ -193,6 +193,18 @@ abstract_target 'RiotPods' do import_MatrixSDK end + # Disabled due to crypto corruption issues. + # https://github.com/vector-im/element-ios/issues/7618 + # target "RiotShareExtension" do + # import_MatrixSDK + # import_MatrixKit_pods + # end + # + # target "SiriIntents" do + # import_MatrixSDK + # import_MatrixKit_pods + # end + end post_install do |installer| diff --git a/Podfile.lock b/Podfile.lock index bdbbb2d00..2254e7cdd 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -20,13 +20,31 @@ PODS: - Down (0.11.0) - DSBottomSheet (0.3.0) - DSWaveformImage (6.1.1) + - DTCoreText (1.6.26): + - DTCoreText/Core (= 1.6.26) + - DTFoundation/Core (~> 1.7.5) + - DTFoundation/DTAnimatedGIF (~> 1.7.5) + - DTFoundation/DTHTMLParser (~> 1.7.5) + - DTFoundation/UIKit (~> 1.7.5) + - DTCoreText/Core (1.6.26): + - DTFoundation/Core (~> 1.7.5) + - DTFoundation/DTAnimatedGIF (~> 1.7.5) + - DTFoundation/DTHTMLParser (~> 1.7.5) + - DTFoundation/UIKit (~> 1.7.5) + - DTFoundation/Core (1.7.18) + - DTFoundation/DTAnimatedGIF (1.7.18) + - DTFoundation/DTHTMLParser (1.7.18): + - DTFoundation/Core + - DTFoundation/UIKit (1.7.18): + - DTFoundation/Core + - DTTJailbreakDetection (0.4.0) - FLEX (4.5.0) - FlowCommoniOS (1.12.2) - GBDeviceInfo (7.1.0): - GBDeviceInfo/Core (= 7.1.0) - GBDeviceInfo/Core (7.1.0) - GZIP (1.3.0) - - Introspect (0.1.4) + - Introspect (0.12.0) - JitsiMeetSDKLite (8.1.2-lite): - JitsiWebRTC (~> 111.0) - JitsiWebRTC (111.0.2) @@ -39,26 +57,29 @@ PODS: - LoggerAPI (1.9.200): - Logging (~> 1.1) - Logging (1.4.0) - - MatrixSDK (0.26.12): - - MatrixSDK/Core (= 0.26.12) - - MatrixSDK/Core (0.26.12): + - MatomoTracker (7.5.2): + - MatomoTracker/Core (= 7.5.2) + - MatomoTracker/Core (7.5.2) + - MatrixSDK (0.27.1): + - MatrixSDK/Core (= 0.27.1) + - MatrixSDK/Core (0.27.1): - AFNetworking (~> 4.0.0) - GZIP (~> 1.3.0) - libbase58 (~> 0.1.4) - - MatrixSDKCrypto (= 0.3.4) + - MatrixSDKCrypto (= 0.3.12) - OLMKit (~> 3.2.5) - Realm (= 10.27.0) - SwiftyBeaver (= 1.9.5) - - MatrixSDK/JingleCallStack (0.26.12): + - MatrixSDK/JingleCallStack (0.27.1): - JitsiMeetSDKLite (= 8.1.2-lite) - MatrixSDK/Core - - MatrixSDKCrypto (0.3.4) + - MatrixSDKCrypto (0.3.12) - OLMKit (3.2.12): - OLMKit/olmc (= 3.2.12) - OLMKit/olmcpp (= 3.2.12) - OLMKit/olmc (3.2.12) - OLMKit/olmcpp (3.2.12) - - PostHog (2.0.0) + - PostHog (2.0.2) - ReadMoreTextView (3.0.1) - Realm (10.27.0): - Realm/Headers (= 10.27.0) @@ -73,7 +94,7 @@ PODS: - Sentry/Core (7.15.0) - SideMenu (6.5.0) - SwiftBase32 (0.9.0) - - SwiftFormat/CLI (0.50.2) + - SwiftFormat/CLI (0.52.3) - SwiftGen (6.6.2) - SwiftJWT (3.6.200): - BlueCryptor (~> 1.0) @@ -81,7 +102,7 @@ PODS: - BlueRSA (~> 1.0) - KituraContracts (~> 1.2) - LoggerAPI (~> 1.7) - - SwiftLint (0.49.1) + - SwiftLint (0.52.4) - SwiftyBeaver (1.9.5) - UICollectionViewLeftAlignedLayout (1.0.2) - UICollectionViewRightAlignedLayout (0.0.3) @@ -95,6 +116,8 @@ DEPENDENCIES: - Down (~> 0.11.0) - DSBottomSheet (~> 0.3) - DSWaveformImage (~> 6.1.1) + - DTCoreText (= 1.6.26) + - DTTJailbreakDetection (~> 0.4.0) - FLEX (~> 4.5.0) - FlowCommoniOS (~> 1.12.0) - GBDeviceInfo (~> 7.1.0) @@ -102,8 +125,9 @@ DEPENDENCIES: - KeychainAccess (~> 4.2.2) - KTCenterFlowLayout (~> 1.3.1) - libPhoneNumber-iOS (~> 0.9.13) - - MatrixSDK (= 0.26.12) - - MatrixSDK/JingleCallStack (= 0.26.12) + - MatomoTracker (~> 7.5.2) + - MatrixSDK (from `https://dl-gitlab.example.com/bwmessenger/bundesmessenger/bundesmessenger-ios-sdk`, tag `v2.10.0_rc2`) + - MatrixSDK/JingleCallStack (from `https://dl-gitlab.example.com/bwmessenger/bundesmessenger/bundesmessenger-ios-sdk`, tag `v2.10.0_rc2`) - OLMKit - PostHog (~> 2.0.0) - ReadMoreTextView (~> 3.0.1) @@ -122,7 +146,7 @@ DEPENDENCIES: - ZXingObjC (~> 3.6.5) SPEC REPOS: - trunk: + https://github.com/CocoaPods/Specs.git: - AFNetworking - BlueCryptor - BlueECC @@ -130,6 +154,9 @@ SPEC REPOS: - Down - DSBottomSheet - DSWaveformImage + - DTCoreText + - DTFoundation + - DTTJailbreakDetection - FLEX - FlowCommoniOS - GBDeviceInfo @@ -144,7 +171,7 @@ SPEC REPOS: - libPhoneNumber-iOS - LoggerAPI - Logging - - MatrixSDK + - MatomoTracker - MatrixSDKCrypto - OLMKit - PostHog @@ -165,6 +192,16 @@ SPEC REPOS: - zxcvbn-ios - ZXingObjC +EXTERNAL SOURCES: + MatrixSDK: + :git: https://dl-gitlab.example.com/bwmessenger/bundesmessenger/bundesmessenger-ios-sdk + :tag: v2.10.0_rc2 + +CHECKOUT OPTIONS: + MatrixSDK: + :git: https://dl-gitlab.example.com/bwmessenger/bundesmessenger/bundesmessenger-ios-sdk + :tag: v2.10.0_rc2 + SPEC CHECKSUMS: AFNetworking: 3bd23d814e976cd148d7d44c3ab78017b744cd58 BlueCryptor: b0aee3d9b8f367b49b30de11cda90e1735571c24 @@ -173,11 +210,14 @@ SPEC CHECKSUMS: Down: b6ba1bc985c9d2f4e15e3b293d2207766fa12612 DSBottomSheet: ca0ac37eb5af2dd54663f86b84382ed90a59be2a DSWaveformImage: 3c718a0cf99291887ee70d1d0c18d80101d3d9ce + DTCoreText: ec749e013f2e1f76de5e7c7634642e600a7467ce + DTFoundation: a53f8cda2489208cbc71c648be177f902ee17536 + DTTJailbreakDetection: 5e356c5badc17995f65a83ed9483f787a0057b71 FLEX: e51461dd6f0bfb00643c262acdfea5d5d12c596b FlowCommoniOS: ca92071ab526dc89905495a37844fd7e78d1a7f2 GBDeviceInfo: 5d62fa85bdcce3ed288d83c28789adf1173e4376 GZIP: 416858efbe66b41b206895ac6dfd5493200d95b3 - Introspect: b62c4dd2063072327c21d618ef2bedc3c87bc366 + Introspect: b66b675de8a85d9ef832f3a710d8e3c7db186884 JitsiMeetSDKLite: 895213158cf62342069a10634a41d2f1c00057f7 JitsiWebRTC: 80f62908fcf2a1160e0d14b584323fb6e6be630b KeychainAccess: c0c4f7f38f6fc7bbe58f5702e25f7bd2f65abf51 @@ -187,20 +227,21 @@ SPEC CHECKSUMS: libPhoneNumber-iOS: 0a32a9525cf8744fe02c5206eb30d571e38f7d75 LoggerAPI: ad9c4a6f1e32f518fdb43a1347ac14d765ab5e3d Logging: beeb016c9c80cf77042d62e83495816847ef108b - MatrixSDK: 0af737bc461b82d0ec9edd6fdf8f70b02771ebd3 - MatrixSDKCrypto: ac805c22c24f79f349cdbfa065855c73a4c81b51 + MatomoTracker: 1d98ddc58322fd9d65e1a6886b8e41363047bd13 + MatrixSDK: f6c197ca06aab29ff69d1105965a57d277dfcd9d + MatrixSDKCrypto: 25929a40733b4ab54f659aaf6a730552a0a06504 OLMKit: da115f16582e47626616874e20f7bb92222c7a51 - PostHog: 660ec6c9d80cec17b685e148f17f6785a88b597d + PostHog: f9e5c13ceea86bb5314218c85d16125b797eb332 ReadMoreTextView: 19147adf93abce6d7271e14031a00303fe28720d Realm: 9ca328bd7e700cc19703799785e37f77d1a130f2 Reusable: 6bae6a5e8aa793c9c441db0213c863a64bce9136 Sentry: 63ca44f5e0c8cea0ee5a07686b02e56104f41ef7 SideMenu: f583187d21c5b1dd04c72002be544b555a2627a2 SwiftBase32: 9399c25a80666dc66b51e10076bf591e3bbb8f17 - SwiftFormat: 710117321c55c82675c0dc03055128efbb13c38f + SwiftFormat: 5de81c42f043741a16e17ae2da012bbddc7c0b58 SwiftGen: 1366a7f71aeef49954ca5a63ba4bef6b0f24138c SwiftJWT: 88c412708f58c169d431d344c87bc79a87c830ae - SwiftLint: 32ee33ded0636d0905ef6911b2b67bbaeeedafa5 + SwiftLint: 1cc5cd61ba9bacb2194e340aeb47a2a37fda00b3 SwiftyBeaver: 84069991dd5dca07d7069100985badaca7f0ce82 UICollectionViewLeftAlignedLayout: 830bf6fa5bab9f9b464f62e3384f9d2e00b3c0f6 UICollectionViewRightAlignedLayout: 823eef8c567eba4a44c21bc2ffcb0d0d5f361e2d @@ -208,6 +249,6 @@ SPEC CHECKSUMS: zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb -PODFILE CHECKSUM: 0e7e10f516d40d9df60cb874170b91603c632118 +PODFILE CHECKSUM: e7f4847564a30ed02659a311fe204021498f30e8 COCOAPODS: 1.11.3 diff --git a/Riot/Assets/Images.xcassets/BWI/button_new_dark.imageset/Button_BuM_Dark.svg b/Riot/Assets/Images.xcassets/BWI/button_new_dark.imageset/Button_BuM_Dark.svg new file mode 100644 index 000000000..0f0658a77 --- /dev/null +++ b/Riot/Assets/Images.xcassets/BWI/button_new_dark.imageset/Button_BuM_Dark.svg @@ -0,0 +1,17 @@ + diff --git a/Riot/Assets/Images.xcassets/BWI/button_new_dark.imageset/Contents.json b/Riot/Assets/Images.xcassets/BWI/button_new_dark.imageset/Contents.json new file mode 100644 index 000000000..0ed753627 --- /dev/null +++ b/Riot/Assets/Images.xcassets/BWI/button_new_dark.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Button_BuM_Dark.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Riot/Assets/Images.xcassets/BWI/button_new_light.imageset/Button_BuM_Light.svg b/Riot/Assets/Images.xcassets/BWI/button_new_light.imageset/Button_BuM_Light.svg new file mode 100644 index 000000000..c9f8c0b29 --- /dev/null +++ b/Riot/Assets/Images.xcassets/BWI/button_new_light.imageset/Button_BuM_Light.svg @@ -0,0 +1,17 @@ + diff --git a/Riot/Assets/Images.xcassets/BWI/button_new_light.imageset/Contents.json b/Riot/Assets/Images.xcassets/BWI/button_new_light.imageset/Contents.json new file mode 100644 index 000000000..b6b5b9fa7 --- /dev/null +++ b/Riot/Assets/Images.xcassets/BWI/button_new_light.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Button_BuM_Light.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Riot/Assets/Images.xcassets/BWI/bwi_settings_filled.imageset/Contents.json b/Riot/Assets/Images.xcassets/BWI/bwi_settings_filled.imageset/Contents.json new file mode 100644 index 000000000..b76053693 --- /dev/null +++ b/Riot/Assets/Images.xcassets/BWI/bwi_settings_filled.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "settings-filled.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Riot/Assets/Images.xcassets/BWI/bwi_settings_filled.imageset/settings-filled.svg b/Riot/Assets/Images.xcassets/BWI/bwi_settings_filled.imageset/settings-filled.svg new file mode 100644 index 000000000..82adbb752 --- /dev/null +++ b/Riot/Assets/Images.xcassets/BWI/bwi_settings_filled.imageset/settings-filled.svg @@ -0,0 +1,8 @@ + diff --git a/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_dark_off.imageset/Contents.json b/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_dark_off.imageset/Contents.json new file mode 100644 index 000000000..67ec47a7c --- /dev/null +++ b/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_dark_off.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Filter-dark.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_dark_off.imageset/Filter-dark.svg b/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_dark_off.imageset/Filter-dark.svg new file mode 100644 index 000000000..c0e66be50 --- /dev/null +++ b/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_dark_off.imageset/Filter-dark.svg @@ -0,0 +1,3 @@ + diff --git a/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_dark_on.imageset/Contents.json b/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_dark_on.imageset/Contents.json new file mode 100644 index 000000000..068ead335 --- /dev/null +++ b/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_dark_on.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Filter-pressed-dark.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_dark_on.imageset/Filter-pressed-dark.svg b/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_dark_on.imageset/Filter-pressed-dark.svg new file mode 100644 index 000000000..37c1861f3 --- /dev/null +++ b/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_dark_on.imageset/Filter-pressed-dark.svg @@ -0,0 +1,11 @@ + diff --git a/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_light_off.imageset/Contents.json b/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_light_off.imageset/Contents.json new file mode 100644 index 000000000..aebe7c313 --- /dev/null +++ b/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_light_off.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Filter-light.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_light_off.imageset/Filter-light.svg b/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_light_off.imageset/Filter-light.svg new file mode 100644 index 000000000..bd03bf038 --- /dev/null +++ b/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_light_off.imageset/Filter-light.svg @@ -0,0 +1,3 @@ + diff --git a/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_light_on.imageset/Contents.json b/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_light_on.imageset/Contents.json new file mode 100644 index 000000000..2f3d3968c --- /dev/null +++ b/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_light_on.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Filter-pressed-light.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_light_on.imageset/Filter-pressed-light.svg b/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_light_on.imageset/Filter-pressed-light.svg new file mode 100644 index 000000000..7ec32495e --- /dev/null +++ b/Riot/Assets/Images.xcassets/BWI/room_filter_toggle_light_on.imageset/Filter-pressed-light.svg @@ -0,0 +1,11 @@ + diff --git a/Riot/Assets/Images.xcassets/PersonalNotes/personal_notes_avatar.imageset/BWI-noticeboard.png b/Riot/Assets/Images.xcassets/PersonalNotes/personal_notes_avatar.imageset/BWI-noticeboard.png deleted file mode 100644 index 7d993a44d..000000000 Binary files a/Riot/Assets/Images.xcassets/PersonalNotes/personal_notes_avatar.imageset/BWI-noticeboard.png and /dev/null differ diff --git a/Riot/Assets/Images.xcassets/PersonalNotes/personal_notes_avatar.imageset/Contents.json b/Riot/Assets/Images.xcassets/PersonalNotes/personal_notes_avatar.imageset/Contents.json index 4c8d4000f..a54b8e9bc 100644 --- a/Riot/Assets/Images.xcassets/PersonalNotes/personal_notes_avatar.imageset/Contents.json +++ b/Riot/Assets/Images.xcassets/PersonalNotes/personal_notes_avatar.imageset/Contents.json @@ -9,7 +9,7 @@ "scale" : "2x" }, { - "filename" : "BWI-noticeboard.png", + "filename" : "Notizen-Avatar.svg", "idiom" : "universal", "scale" : "3x" } diff --git a/Riot/Assets/Images.xcassets/PersonalNotes/personal_notes_avatar.imageset/Notizen-Avatar.svg b/Riot/Assets/Images.xcassets/PersonalNotes/personal_notes_avatar.imageset/Notizen-Avatar.svg new file mode 100644 index 000000000..7cdaae305 --- /dev/null +++ b/Riot/Assets/Images.xcassets/PersonalNotes/personal_notes_avatar.imageset/Notizen-Avatar.svg @@ -0,0 +1,4 @@ + diff --git a/Riot/Assets/de.lproj/Bwi.strings b/Riot/Assets/de.lproj/Bwi.strings index 15b7d1b85..42fa341ff 100644 --- a/Riot/Assets/de.lproj/Bwi.strings +++ b/Riot/Assets/de.lproj/Bwi.strings @@ -52,6 +52,16 @@ "bwi_settings_developer_restrict_user" = "Nutzer einschränken"; "bwi_settings_developer_unrestrict_user" = "Nutzereinschränkung aufheben"; "bwi_settings_developer_unmark_banner" = "Banner als nicht gelesen markieren"; +"bwi_settings_developer_well_known" = "Well-Known"; +"bwi_settings_developer_capabilities" = "Capabilities"; +"bwi_settings_developer_maintenance" = "Maintenance"; +"bwi_settings_developer_user_account_data" = "Account Data"; +"bwi_settings_developer_user_account_data_type" = "Type"; +"bwi_settings_developer_key_backup" = "Key Backup"; +"bwi_settings_developer_key_backup_algorithm" = "Algorithmus"; +"bwi_settings_developer_key_backup_count" = "Gespeicherte Schlüssel"; +"bwi_settings_developer_key_backup_etag" = "ETag"; +"bwi_settings_developer_key_backup_version" = "Version"; // MARK: - MDM @@ -198,7 +208,7 @@ "settings_old_password" = "Aktuelles Passwort"; "settings_new_password" = "Neues Passwort"; "settings_confirm_password" = "Neues Passwort bestätigen"; -"settings_password_updated" = "Dein Passwort wurde aktualisiert"; +"settings_password_changed" = "Dein Passwort wurde erfolgreich geändert."; "settings_password_condition" = "Regeln: Mindestlänge 8 Zeichen, mind. 1 Sonderzeichen, 1 Groß- und 1 Kleinbuchstaben und 1 Ziffer"; "settings_password_too_short_message" = "Das Passwort muss aus mindestens 8 Zeichen bestehen"; "settings_password_has_no_digit" = "Das Passwort muss mindestens eine Ziffer enthalten"; @@ -407,7 +417,7 @@ "voice_message_remaining_recording_time" = "noch %@s"; "voice_message_stop_locked_mode_recording" = "Klick die Nachricht um zu stoppen oder zu hören"; "voice_message_lock_screen_placeholder" = "Sprachnachricht"; -"voice_message_slide_to_cancel" = "Sliden zum Abbrechen"; +"voice_message_slide_to_cancel" = "Wischen zum Abbrechen"; // MARK: - Developer Menu @@ -429,6 +439,7 @@ "bwi_settings_enable_notes_room_title" = "Zeige meine Notizen"; "bwi_settings_enable_notes_room_summary" = "Einen Raum für private Notizen anzeigen"; "bwi_notes_room_title" = "Meine Notizen"; +"home_context_menu_personal_notes" = "Notizen ausblenden"; // MARK: - Personal State @@ -505,6 +516,7 @@ "bwi_error_invite_banned_in_room" = "%@ ist vom Raum gebannt."; "bwi_error_invite_general" = "%@ konnte nicht eingeladen werden."; "bwi_error_logout_offline" = "Abmelden ist ohne Internetverbindung nicht möglich."; +"bwi_error_invalid_password" = "Falsches Passwort"; // MARK: - Matomo @@ -523,7 +535,7 @@ "bwi_settings_new_features_show_features" = "Neue Funktionen anzeigen"; "bwi_feature_banner_header" = "Neue Funktionen"; "bwi_feature_banner_show_more_button" = "Erfahre mehr"; -"bwi_feature_banner_advertisement_text" = "Mit dem neuen Feature Ruhezeiteneinstellung lassen sich Benachrichtigungen nach Wochentag und Uhrzeit ein- bzw stummschalten."; +"bwi_feature_banner_advertisement_text" = "Beim Schreiben von Nachrichten kannst Du jetzt sehr einfach Textformatierungen verwenden."; // MARK: - Onboarding "onboarding_splash_login_button_title" = "Loslegen"; @@ -548,6 +560,8 @@ "poll_timeline_show_participants_button" = "Stimmen ansehen"; "poll_participant_details_show_more" = "Alle ansehen (%lu weitere)"; "poll_participant_details_title" = "Umfragedetails"; +"poll_participant_details_clock_string" = " Uhr"; +"poll_participant_details_date_string_today" = "Heute, "; // MARK: - Welcome Experience "welcome_experience_title1" = "Willkommen beim BundesMessenger"; @@ -584,6 +598,7 @@ // MARK: - New Layout "all_chats_edit_layout_show_personal_notes" = "Notizenraum anzeigen"; +"all_chats_searchbar_prompt" = "Suche"; // MARK: - Permalink Scan "room_recents_scan_qr_code" = "QR Code scannen"; diff --git a/Riot/Assets/de.lproj/Vector.strings b/Riot/Assets/de.lproj/Vector.strings index d6a80382a..578b85782 100644 --- a/Riot/Assets/de.lproj/Vector.strings +++ b/Riot/Assets/de.lproj/Vector.strings @@ -406,8 +406,8 @@ "settings_ui_language" = "Sprache"; // Events formatter "event_formatter_member_updates" = "%tu Änderungen der Mitgliedschaft"; -"contacts_user_directory_section" = "NUTZER VERZEICHNIS"; -"contacts_user_directory_offline_section" = "NUTZER VERZEICHNIS (offline)"; +"contacts_user_directory_section" = "NUTZERVERZEICHNIS"; +"contacts_user_directory_offline_section" = "NUTZERVERZEICHNIS (offline)"; "auth_home_server_placeholder" = "URL (z.B. https://matrix.org)"; "auth_identity_server_placeholder" = "URL (z. B. https://vector.im)"; "room_ongoing_conference_call_close" = "Schließen"; @@ -2396,12 +2396,12 @@ "room_suggestion_settings_screen_nav_title" = "Raum vorschlagen"; "room_access_space_chooser_other_spaces_section_info" = "Diese sind vermutlich Dinge, zu denen andere Admins von %@ gehören."; "room_access_space_chooser_other_spaces_section" = "Andere Spaces oder Räume"; -"room_access_settings_screen_setting_room_access" = "Lege Raumzugriff fest"; -"room_access_settings_screen_upgrade_alert_upgrading" = "Raum upgraden"; +"room_access_settings_screen_setting_room_access" = "Raumzutritt festlegen"; +"room_access_settings_screen_upgrade_alert_upgrading" = "Raum aktualisieren"; "room_access_settings_screen_upgrade_alert_upgrade_button" = "Aktualisieren"; "room_access_settings_screen_upgrade_alert_auto_invite_switch" = "Mitglieder automatisch zu neuem Raum einladen"; -"room_access_settings_screen_upgrade_alert_message" = "Jeder in %@ kann diesen Raum finden und ihm beitreten - jeden manuell einzuladen ist nicht nötig. Du kannst diese Einstellung jederzeit ändern."; -"room_access_settings_screen_upgrade_alert_title" = "Raum upgraden"; +"room_access_settings_screen_upgrade_alert_message" = "Jeder in %@ kann diesen Raum finden und ihm beitreten – jeden manuell einzuladen ist nicht nötig. Du kannst diese Einstellung jederzeit ändern."; +"room_access_settings_screen_upgrade_alert_title" = "Raum aktualisieren"; "room_access_settings_screen_edit_spaces" = "Spaces bearbeiten"; "room_access_settings_screen_upgrade_required" = "Upgrade erforderlich"; "room_access_settings_screen_message" = "Lege fest, wer %@ finden und beitreten kann."; @@ -2452,7 +2452,7 @@ // Mark: - All Chats -"all_chats_title" = "Alle Unterhaltungen"; +"all_chats_title" = "Unterhaltungen"; "all_chats_empty_view_title" = "%@\nsieht ein bisschen leer aus."; "all_chats_all_filter" = "Alle"; "all_chats_edit_layout_show_filters" = "Filter anzeigen"; @@ -2461,13 +2461,13 @@ "threads_discourage_information_1" = "Dein Heimserver unterstützt aktuell keine Threads, weshalb diese Funktion unzuverlässig sein könnte. Manche Thread-Nachrichten könnten nicht zuverlässig verfügbar sein. "; "all_chats_nothing_found_placeholder_title" = "Nichts gefunden."; "spaces_create_subspace_title" = "Sub-Space erstellen"; -"room_access_settings_screen_upgrade_alert_note" = "Bitte beachte, dass das Upgrade eine neue Version dieses Raums erstellt. Alle aktuellen Nachrichten bleiben in diesem archivierten Raum."; +"room_access_settings_screen_upgrade_alert_note" = "Bitte beachte, dass die Aktualisierung eine neue Version dieses Raums erstellt. Alle aktuellen Nachrichten bleiben in diesem archivierten Raum."; "invite_to" = "Zu %@ einladen"; "all_chats_empty_unreads_placeholder_message" = "Hier werden deine ungelesenen Nachrichten erscheinen, wenn du welche hast."; "all_chats_edit_layout_show_recents" = "Historie anzeigen"; "all_chats_empty_list_placeholder_title" = "Du bist auf dem neuesten Stand."; "spaces_explore_rooms_format" = "%@ erkunden"; -"room_access_settings_screen_upgrade_alert_message_no_param" = "Jeder in einem übergeordneten Space kann diesen Raum finden und ihm beitreten - jeden manuell einzuladen ist nicht nötig. Du kannst diese Einstellung jederzeit ändern."; +"room_access_settings_screen_upgrade_alert_message_no_param" = "Jeder in einem übergeordneten Space kann diesen Raum finden und ihm beitreten – jeden manuell einzuladen ist nicht nötig. Du kannst diese Einstellung jederzeit ändern."; "room_access_settings_screen_public_message" = "Sichtbar und zugänglich für jeden."; "room_access_settings_screen_restricted_message" = "Sichtbar und betretbar für jeden Nutzer in einem Space.\nDu wählst, für welche Spaces dies gilt."; "room_access_settings_screen_private_message" = "Nur sichtbar und betretbar für eingeladene Personen."; @@ -2771,3 +2771,8 @@ "notice_display_name_changed_to" = "%@ hat den Anzeigenamen zu %@ geändert"; "poll_timeline_loading" = "Lade …"; "room_command_discard_session_description" = "Erzwingt das Verferfen der aktuell ausgehende Gruppensitzung in einem verschlüsseltem Raum"; +"room_creation_user_not_found_prompt_title" = "Bestätigung"; +"room_creation_user_not_found_prompt_message" = "Wir konnten kein Profil für diese Matrix-ID finden. Möchtest du dennoch eine Direktnachricht beginnen?"; +"room_creation_user_not_found_prompt_invite_action" = "Dennoch DM beginnen"; +"room_participants_invite_unknown_participant_prompt_to_msg" = "Wir konnten kein Profil für diese Matrix-ID finden. Möchtest du wirklich %@ nach %@ einladen?"; +"room_participants_invite_anyway" = "Dennoch einladen"; diff --git a/Riot/Assets/en.lproj/Bwi.strings b/Riot/Assets/en.lproj/Bwi.strings index 828c1d18e..6267f0522 100644 --- a/Riot/Assets/en.lproj/Bwi.strings +++ b/Riot/Assets/en.lproj/Bwi.strings @@ -53,6 +53,16 @@ "bwi_settings_developer_restrict_user" = "Restrict user"; "bwi_settings_developer_unrestrict_user" = "Remove user restriction"; "bwi_settings_developer_unmark_banner" = "Unmark Feature Banner"; +"bwi_settings_developer_well_known" = "Well-Known"; +"bwi_settings_developer_capabilities" = "Capabilities"; +"bwi_settings_developer_maintenance" = "Maintenance"; +"bwi_settings_developer_user_account_data" = "Account Data"; +"bwi_settings_developer_user_account_data_type" = "Type"; +"bwi_settings_developer_key_backup" = "Key Backup"; +"bwi_settings_developer_key_backup_algorithm" = "Algorithm"; +"bwi_settings_developer_key_backup_count" = "Stored Keys"; +"bwi_settings_developer_key_backup_etag" = "ETag"; +"bwi_settings_developer_key_backup_version" = "Version"; // MARK: - MDM @@ -154,7 +164,7 @@ "settings_new_password" = "new password"; "settings_confirm_password" = "confirm password"; "settings_fail_to_update_password" = "Fail to update password"; -"settings_password_updated" = "Your password has been updated"; +"settings_password_changed" = "Your password has been changed."; "settings_password_condition" = "Rules: Minimum length 8 characters, at least 1 special character, 1 uppercase and 1 lowercase letter and 1 number"; "settings_password_too_short_message" = "The password must be at least 8 characters long"; "settings_password_has_no_digit" = "The password must include at least one digit"; @@ -342,6 +352,7 @@ "bwi_settings_enable_notes_room_title" = "My notes"; "bwi_settings_enable_notes_room_summary" = "how personal notes room."; "bwi_notes_room_title" = "My notes"; +"home_context_menu_personal_notes" = "Hide notes"; // MARK: - Personal State @@ -414,6 +425,7 @@ "bwi_error_invite_banned_in_room" = "%@ is banned from the room."; "bwi_error_invite_general" = "%@ could not be invited."; "bwi_error_logout_offline" = "Logout not possible without internet connection."; +"bwi_error_invalid_password" = "Invalid password"; // MARK: - Matomo @@ -432,7 +444,7 @@ "bwi_settings_new_features_show_features" = "Show new features"; "bwi_feature_banner_header" = "New Features"; "bwi_feature_banner_show_more_button" = "Learn more"; -"bwi_feature_banner_advertisement_text" = "A new feature for notifications times allows you to define time intervals for filtering incoming push notifications."; +"bwi_feature_banner_advertisement_text" = "You can now easily use text formatting when writing messages."; // MARK: - Onboarding "onboarding_splash_login_button_title" = "Let's go"; @@ -453,6 +465,8 @@ "poll_timeline_show_participants_button" = "Show votes"; "poll_participant_details_show_more" = "Show all (%lu more)"; "poll_participant_details_title" = "Poll details"; +"poll_participant_details_clock_string" = ""; +"poll_participant_details_date_string_today" = "Today, "; // MARK: - Welcome Experience "welcome_experience_title1" = "Welcome to BundesMessenger"; @@ -494,6 +508,7 @@ // MARK: - New Layout "all_chats_edit_layout_show_personal_notes" = "Show personal notes"; +"all_chats_searchbar_prompt" = "Suche"; // MARK: - Permalink Scan "room_recents_scan_qr_code" = "Scan QR Code"; diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index e22420771..432f8ed23 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -748,6 +748,9 @@ Tap the + to start adding people."; "settings_three_pids_management_information_part1" = "Manage which email addresses or phone numbers you can use to log in or recover your account here. Control who can find you in "; "settings_three_pids_management_information_part2" = "Discovery"; "settings_three_pids_management_information_part3" = "."; +"settings_manage_account_title" = "Account"; +"settings_manage_account_action" = "Manage account"; +"settings_manage_account_description" = "Manage your account at %@"; "settings_confirm_media_size" = "Confirm size when sending"; "settings_confirm_media_size_description" = "When this is on, you’ll be asked to confirm what size images and videos will be sent as."; @@ -964,6 +967,8 @@ Tap the + to start adding people."; "manage_session_trusted" = "Trusted by you"; "manage_session_not_trusted" = "Not trusted"; "manage_session_sign_out" = "Sign out of this session"; +"manage_session_redirect" = "You will be redirected to your server's authentication provider to complete sign out."; +"manage_session_redirect_error" = "Functionality currently unavailable. Please contact your homeserver admin"; "manage_session_rename" = "Rename session"; "manage_session_sign_out_other_sessions" = "Sign out of all other sessions"; // User sessions management @@ -2279,7 +2284,7 @@ Tap the + to start adding people."; // MARK: - All Chats -"all_chats_title" = "All chats"; +"all_chats_title" = "Chats"; "all_chats_section_title" = "Chats"; "all_chats_edit_layout" = "Layout preferences"; "all_chats_edit_layout_recents" = "Recents"; diff --git a/Riot/Assets/eo.lproj/Vector.strings b/Riot/Assets/eo.lproj/Vector.strings index 2e91114ed..a09965843 100644 --- a/Riot/Assets/eo.lproj/Vector.strings +++ b/Riot/Assets/eo.lproj/Vector.strings @@ -1968,7 +1968,7 @@ "notice_encrypted_message" = "Ĉifrita mesaĝo"; "notice_room_related_groups" = "Grupoj rilataj al ĉi tiu ĉambro estas: %@"; "notice_room_aliases_for_dm" = "La kromnomoj estas: %@"; -"notice_room_aliases" = "Kromnomoj de la ĉamrbo estas: %@"; +"notice_room_aliases" = "Kromnomoj de la ĉambro estas: %@"; "notice_room_power_level_event_requirement" = "La minimumaj povniveloj rilataj al okazoj estas:"; "notice_room_power_level_acting_requirement" = "La minimuma povnivelo, kiun uzanto bezonas antaŭ agi, estas:"; "notice_room_power_level_intro_for_dm" = "La povniveloj de ĉambranoj estas:"; diff --git a/Riot/Assets/et.lproj/Vector.strings b/Riot/Assets/et.lproj/Vector.strings index 21f95be98..0cad547d7 100644 --- a/Riot/Assets/et.lproj/Vector.strings +++ b/Riot/Assets/et.lproj/Vector.strings @@ -2709,3 +2709,8 @@ "room_command_change_display_name_description" = "Muudab sinu kuvatavat nime"; "notice_display_name_changed_to" = "%@ muutis oma kuvatavaks nimeks %@"; "poll_timeline_loading" = "Laadin..."; +"room_creation_user_not_found_prompt_title" = "Kinnitus"; +"room_creation_user_not_found_prompt_invite_action" = "Ikkagi alusta vestlust"; +"room_creation_user_not_found_prompt_message" = "Sellele Matrix'i kasutajatunnuse profiili ei leidu. Kas sa ikkagi tahaksid temaga vestlust alustada?"; +"room_participants_invite_unknown_participant_prompt_to_msg" = "Sellele Matrix'i kasutajatunnuse profiili ei leidu. Kas sa ikkagi tahaksid saata kutset kasutajale %@ jututuppa %@?"; +"room_participants_invite_anyway" = "Kutsu siiski"; diff --git a/Riot/Assets/it.lproj/Vector.strings b/Riot/Assets/it.lproj/Vector.strings index 81f489410..d3c3cf5c5 100644 --- a/Riot/Assets/it.lproj/Vector.strings +++ b/Riot/Assets/it.lproj/Vector.strings @@ -274,7 +274,7 @@ "room_title_members" = "%@ membri"; "room_title_one_member" = "1 membro"; // Room Preview -"room_preview_invitation_format" = "Sei stato invitato ad entrare in questa stanza da %@"; +"room_preview_invitation_format" = "Sei stato/a invitato/a ad entrare in questa stanza da %@"; "room_preview_subtitle" = "Questa è l'anteprima della stanza. Le interazioni sono disabilitate."; "room_preview_unlinked_email_warning" = "Questo invito è stato spedito a %@, che non è associato a questo account. Puoi aggiungere questa email al tuo account o provare ad accedere con un account differente."; "room_preview_try_join_an_unknown_room" = "Stai provando ad accedere a %@. Desideri entrare per partecipare alla discussione?"; @@ -457,7 +457,7 @@ "group_home_multi_members_format" = "%tu membri"; "group_home_one_room_format" = "1 stanza"; "group_home_multi_rooms_format" = "%tu stanze"; -"group_invitation_format" = "%@ ti ha invitato ad unirti a questa comunità"; +"group_invitation_format" = "%@ ti ha invitato/a ad unirti a questa comunità"; // Group participants "group_participants_add_participant" = "Aggiungi membri"; "group_participants_leave_prompt_title" = "Lascia la stanza"; @@ -649,7 +649,7 @@ "sign_out_key_backup_in_progress_alert_cancel_action" = "Attendo"; "close" = "Chiudi"; "auth_forgot_password_error_no_configured_identity_server" = "Non è stato configurato alcun server d'identità: aggiungine uno per ripristinare la password dell'account Matrix."; -"auth_softlogout_signed_out" = "Sei uscito"; +"auth_softlogout_signed_out" = "Sei disconnesso/a"; "auth_softlogout_sign_in" = "Accedi"; "auth_softlogout_reason" = "L'amministratore dell'Home Server (%1$@) ti ha disconnesso dal tuo account %2$@ (%3$@)."; "auth_softlogout_recover_encryption_keys" = "Accedi per recuperare le chiavi crittografiche archiviate su questo dispositivo. Le chiavi ti servono per poter leggere i tuoi messaggi cifrati su altri dispositivi."; @@ -1164,7 +1164,7 @@ "biometrics_cant_unlocked_alert_message_login" = "Riaccedi"; "biometrics_cant_unlocked_alert_message_retry" = "Riprova"; "device_verification_self_verify_wait_recover_secrets_checking_availability" = "Controllo di altre possibilità di verifica..."; -"joined" = "Entrato"; +"joined" = "Entrato/a"; "switch" = "Cambia"; "more" = "Altro"; "pin_protection_choose_pin_welcome_after_login" = "Bentornato/a."; @@ -1832,7 +1832,7 @@ "room_error_cannot_load_timeline" = "Caricamento storico dei messaggi fallito"; "room_error_timeline_event_not_found_title" = "Caricamento della posizione nello storico fallito"; "room_error_timeline_event_not_found" = "L'applicazione ha cercato di caricare un punto specifico dello storico dei messaggi in questo canale, ma non è riuscita a trovarlo"; -"room_left" = "Sei uscito dalla stanza"; +"room_left" = "Sei uscito/a dalla stanza"; "room_no_power_to_create_conference_call" = "Hai bisogno del permesso per invitare a iniziare una conferenza in questo canale"; "room_no_conference_call_in_encrypted_rooms" = "Le chiamate in conferenza non sono supportate nei canali criptati"; // Reply to message @@ -1906,7 +1906,7 @@ // Language picker "language_picker_title" = "Scegli una lingua"; "language_picker_default_language" = "Predefinito (%@)"; -"notice_room_invite" = "%@ invitato %@"; +"notice_room_invite" = "%@ ha invitato %@"; "notice_room_third_party_invite" = "%@ ha invitato %@ a unirsi al canale"; "notice_room_third_party_registered_invite" = "%@ ha accettato l'invito per %@"; "notice_room_third_party_revoked_invite" = "%@ ha ritirato l'invito per %@ a unirsi al canale"; @@ -1944,7 +1944,7 @@ "login" = "Entra"; "create_account" = "Crea utente"; "membership_invite" = "Invitati"; -"membership_leave" = "Uscito"; +"membership_leave" = "Uscito/a"; "membership_ban" = "Espulso"; "num_members_one" = "%@ utente"; "num_members_other" = "%@ utenti"; @@ -1979,7 +1979,7 @@ "notification_settings_contain_my_user_name" = "Notifica con un suono i messaggi che contengono il mio nome utente"; "notification_settings_contain_my_display_name" = "Notifica con un suono i messaggi che contengono il mio nome completo"; "notification_settings_just_sent_to_me" = "Notifica con un suono i messaggi inviati solo a me"; -"notification_settings_invite_to_a_new_room" = "Notifica quando sono invitato in un nuovo canale"; +"notification_settings_invite_to_a_new_room" = "Avvisami quando sono invitato/a in una nuova stanza"; "notification_settings_people_join_leave_rooms" = "Notifica quando gli utenti entrano o escono dai canali"; "notification_settings_receive_a_call" = "Notifica quando ricevo una chiamata"; "notification_settings_suppress_from_bots" = "Sopprimi le notifiche dai bot"; @@ -2009,12 +2009,12 @@ "notice_encryption_enabled_unknown_algorithm" = "%1$@ ha attivato la crittografia end-to-end (algoritmo %2$@ non riconosciuto)."; // Notice Events with "You" "notice_room_invite_by_you" = "Hai invitato %@"; -"notice_room_invite_you" = "%@ ti ha invitato"; +"notice_room_invite_you" = "%@ ti ha invitato/a"; "notice_room_third_party_invite_by_you" = "Hai mandato un invito a %@ a unirsi alla stanza"; "notice_room_third_party_registered_invite_by_you" = "Hai accettato l'invito per %@"; "notice_room_third_party_revoked_invite_by_you" = "Hai revocato l'invito per %@ a unirsi alla stanza"; -"notice_room_join_by_you" = "Sei entrato"; -"notice_room_leave_by_you" = "Sei uscito"; +"notice_room_join_by_you" = "Sei entrato/a"; +"notice_room_leave_by_you" = "Sei uscito/a"; "notice_room_reject_by_you" = "Hai rifiutato l'invito"; "notice_room_kick_by_you" = "Hai rimosso %@"; "notice_room_unban_by_you" = "Hai riammesso %@"; @@ -2049,7 +2049,7 @@ "notice_room_join_rule_public" = "%@ ha reso la stanza pubblica."; "notice_room_join_rule_public_by_you" = "Hai reso la stanza pubblica."; "notice_room_name_removed_for_dm" = "%@ ha rimosso il nome"; -"notice_room_created_for_dm" = "%@ è entrato."; +"notice_room_created_for_dm" = "%@ è entrato/a."; "notice_room_join_rule_invite_for_dm" = "%@ l'ha resa solo su invito."; "notice_room_join_rule_invite_by_you_for_dm" = "L'hai resa solo su invito."; "notice_room_join_rule_public_for_dm" = "%@ l'ha resa pubblica."; @@ -2059,7 +2059,7 @@ "notice_room_history_visible_to_members_for_dm" = "%@ ha reso visibili i messaggi futuri a tutti i membri della stanza."; "notice_room_history_visible_to_members_from_invited_point_for_dm" = "%@ ha reso visibili i messaggi futuri a chiunque, dal momento dell'invito."; "notice_room_history_visible_to_members_from_joined_point_for_dm" = "%@ ha reso visibili i messaggi futuri a chiunque, dal momento dell'entrata."; -"room_left_for_dm" = "Sei uscito"; +"room_left_for_dm" = "Sei uscito/a"; "notice_room_third_party_invite_for_dm" = "%@ ha invitato %@"; "notice_room_third_party_revoked_invite_for_dm" = "%@ ha revocato l'invito per %@"; "notice_room_name_changed_for_dm" = "%@ ha cambiato il nome in %@."; @@ -2067,7 +2067,7 @@ "notice_room_third_party_revoked_invite_by_you_for_dm" = "Hai revocato l'invito per %@"; "notice_room_name_changed_by_you_for_dm" = "Hai cambiato il nome in %@."; "notice_room_name_removed_by_you_for_dm" = "Hai rimosso il nome"; -"notice_room_created_by_you_for_dm" = "Sei entrato."; +"notice_room_created_by_you_for_dm" = "Sei entrato/a."; "notice_room_history_visible_to_members_by_you_for_dm" = "Hai reso visibili i messaggi futuri a tutti i membri della stanza."; "notice_room_history_visible_to_members_from_invited_point_by_you_for_dm" = "Hai reso visibili i messaggi futuri a chiunque, dal momento dell'invito."; "notice_room_history_visible_to_members_from_joined_point_by_you_for_dm" = "Hai reso visibili i messaggi futuri a chiunque, dal momento dell'entrata."; @@ -2096,7 +2096,7 @@ "attachment_small_with_resolution" = "Piccolo %@ (~%@)"; "attachment_size_prompt_message" = "Puoi disattivarlo nelle impostazioni."; "attachment_size_prompt_title" = "Conferma dimensione da inviare"; -"room_displayname_all_other_members_left" = "%@ (Uscito)"; +"room_displayname_all_other_members_left" = "%@ (Uscito/a)"; "attachment_unsupported_preview_message" = "Questo tipo di file non è supportato."; "attachment_unsupported_preview_title" = "Anteprima non disponibile"; "message_reply_to_sender_sent_their_location" = "ha condiviso la sua posizione."; @@ -2273,7 +2273,7 @@ "location_sharing_live_list_item_last_update_invalid" = "Ultimo aggiornamento sconosciuto"; "location_sharing_live_list_item_last_update" = "Aggiornato %@ fa"; "location_sharing_live_list_item_sharing_expired" = "Condivisione scaduta"; -"location_sharing_live_list_item_time_left" = "%@ è uscito"; +"location_sharing_live_list_item_time_left" = "%@ è uscito/a"; "location_sharing_live_viewer_title" = "Posizione"; "location_sharing_live_map_callout_title" = "Condividi posizione"; "bug_report_logs_description" = "Per diagnosticare i problemi, i registri di questo client verranno inviati con questo rapporto di errore. Se preferisci inviare solo il testo soprastante, deseleziona:"; @@ -2737,3 +2737,8 @@ "room_command_change_display_name_description" = "Cambia il tuo nome visualizzato"; "notice_display_name_changed_to" = "%@ ha cambiato il suo nome visualizzato in %@"; "poll_timeline_loading" = "Caricamento..."; +"room_creation_user_not_found_prompt_title" = "Conferma"; +"room_creation_user_not_found_prompt_invite_action" = "Inizia il messaggio lo stesso"; +"room_participants_invite_anyway" = "Invita lo stesso"; +"room_participants_invite_unknown_participant_prompt_to_msg" = "Impossibile trovare profili con questo ID Matrix. Vuoi davvero invitare %@ in %@?"; +"room_creation_user_not_found_prompt_message" = "Impossibile trovare profili con questo ID Matrix. Vuoi comunque iniziare un messaggio diretto?"; diff --git a/Riot/Assets/new_features.html b/Riot/Assets/new_features.html index a379e5e7d..91e227f30 100644 --- a/Riot/Assets/new_features.html +++ b/Riot/Assets/new_features.html @@ -26,6 +26,34 @@
++ Version 2.10.0 +
+ ++ Neue Funktionen +
+ Verbesserungen +
+ Behobene Bugs +
Version 2.9.1
diff --git a/Riot/Assets/ru.lproj/Vector.strings b/Riot/Assets/ru.lproj/Vector.strings
index 2f016c5fd..3e96f0ad3 100644
--- a/Riot/Assets/ru.lproj/Vector.strings
+++ b/Riot/Assets/ru.lproj/Vector.strings
@@ -2265,3 +2265,91 @@
// Room Access Settings
"room_access_settings_screen_nav_title" = "Доступ к комнате";
"spaces_coming_soon_detail" = "Эта функция еще не реализована здесь, но она в разработке. На данный момент вы можете сделать это с помощью %@ на своем компьютере.";
+
+// Unverified sessions
+"key_verification_alert_title" = "У вас есть не подтвержденные сессии";
+"key_verification_scan_qr_code_title" = "Сканируйте QR-код";
+"home_context_menu_favourite" = "Любимые";
+"spaces_add_space_title" = "Создать пространство";
+"room_details_promote_room_title" = "Продвигать комнату";
+"room_suggestion_settings_screen_title" = "Сделать комнату предлагаемой в пространстве";
+"analytics_prompt_terms_link_new_user" = "здесь";
+"create_room_suggest_room" = "Предложения для пользователей пространства";
+"room_info_back_button_title" = "Информация о комнате";
+"home_context_menu_make_dm" = "Перейти к людям";
+"create_room_processing" = "Создание комнаты";
+"home_context_menu_unmute" = "Снять заглушку";
+
+// MARK: - Room invite
+
+"room_invite_to_space_option_title" = "К %@";
+"analytics_prompt_yes" = "Да, все классно";
+"create_room_section_footer_type_private" = "Только приглашенные люди могут искать и вступать.";
+"home_context_menu_make_room" = "Перейти к комнатам";
+"create_room_suggest_room_footer" = "Предлагаемые комнаты выдвинуты для участников как лучший выбор для вступления.";
+"home_context_menu_notifications" = "Уведомления";
+"analytics_prompt_terms_link_upgrade" = "здесь";
+"device_verification_self_verify_open_on_other_device_title" = "Откройте %@ на другом вашем устройстве";
+"create_room_section_footer_type_public" = "Только приглашенные люди могут искать и вступать, не только люди из пространства.";
+"home_context_menu_unfavourite" = "Удалить из любимых";
+"home_context_menu_normal_priority" = "Нормальный приоритет";
+"home_context_menu_mute" = "Заглушить";
+"room_access_settings_screen_upgrade_alert_upgrading" = "Улучшение комнаты";
+"room_access_settings_screen_upgrade_alert_upgrade_button" = "Улучшить";
+"key_backup_recover_from_private_key_progress" = "%@%% закончено";
+"room_access_settings_screen_upgrade_alert_title" = "Улучшить комнату";
+"share_extension_low_quality_video_message" = "Отправьте в %@ для лучшего качества или отправьте в пониженном качестве.";
+"settings_acceptable_use" = "Принимаемые политики пользования";
+"room_suggestion_settings_screen_message" = "Предлагаемые комнаты рекламируются среди участников пространства как подходящие для присоединения.";
+/* Note: The placeholder is for the contents of analytics_prompt_terms_link_new_user */
+"analytics_prompt_terms_new_user" = "Вы можете прочитать все наши условия %@.";
+"key_verification_alert_body" = "Перепроверьте надежность сохранности аккаунта.";
+
+// MARK: - Launch loading
+
+"launch_loading_generic" = "Синхронизация ваших разговоров";
+"home_context_menu_mark_as_unread" = "Пометить как непрочитанное";
+
+// MARK: Sign out warning
+
+"sign_out" = "Выйти";
+"room_command_unban_user_description" = "Разблокирует пользователя с указанным ID";
+"device_verification_self_verify_open_on_other_device_information" = "Вам нужно подтвердить эту сессию для того, чтобы прочитать защищенную историю сообщений\n\nОткройте Element на одном из ваших прочих устройств и действуйте по инструкции.";
+"room_command_change_room_topic_description" = "Указывает тему комнаты";
+"room_access_settings_screen_upgrade_required" = "Требуется улучшение";
+"key_verification_scan_qr_code_information_other_user" = "Наведите камеру на QR-код, отображенном на вашем устройстве для подтверждения ваших сессий";
+
+// Room suggestion Settings
+"room_suggestion_settings_screen_nav_title" = "Предложить комнату";
+/* Note: The placeholder is for the contents of analytics_prompt_terms_link_upgrade */
+"analytics_prompt_terms_upgrade" = "Прочитать все наши условия %@. Они подходят?";
+"key_verification_scan_qr_code_information_other_session" = "Наведите камеру на QR-код, отображенном на другом вашем устройстве для подтверждения вашей сессии";
+"key_verification_scan_qr_code_information_other_device" = "Наведите камеру на QR-код, отображенном на другом вашем устройстве для подтверждения этой сессии";
+"create_room_type_restricted" = "Участники пространства";
+"home_context_menu_low_priority" = "Низкий приоритет";
+"share_invite_link_space_text" = "Хэй, вступай в это пространство на %@";
+"create_room_promotion_header" = "ПРОДВИЖЕНИЕ";
+"create_room_show_in_directory_footer" = "Это может помочь людям искать и вступать.";
+"space_invite_not_enough_permission" = "У вас нет разрешения для приглашения людей в это пространство";
+
+// Room commands descriptions
+"room_command_change_display_name_description" = "Изменяет отображаемое имя пользователя";
+"room_command_emote_description" = "Отображает действие";
+"room_command_join_room_description" = "Присоединяться к комнате с указанным адресом";
+"room_command_part_room_description" = "Покинуть комнату";
+"room_command_invite_user_description" = "Добавляет пользователя с указанным ID в текущую комнату";
+"room_command_kick_user_description" = "Удаляет пользователя с указанным ID из этой комнаты";
+"room_command_ban_user_description" = "Блокирует пользователя с указанным ID";
+"room_command_set_user_power_level_description" = "Назначает уровень силы пользователя";
+"room_command_reset_user_power_level_description" = "Разжалует пользователя с указанным ID";
+"room_command_discard_session_description" = "Принудительно отбрасывает текущий исходящий групповой сеанс в зашифрованной комнате";
+"room_command_error_unknown_command" = "Некорректная или необработанная команда";
+
+// Legacy to Rust security upgrade
+
+"key_verification_self_verify_security_upgrade_alert_title" = "Приложение обновлено";
+"key_verification_self_verify_security_upgrade_alert_message" = "Безопасное общение может быть улучшено с новым обновлением. Пожалуйста, проверьте ваше устройство.";
+"device_verification_self_verify_wait_recover_secrets_additional_help" = "Нет доступа к существующей %@ сессии?";
+"key_verification_scan_qr_code_information_new_session" = "Наведите камеру на QR-код, отображенном на другом вашем устройстве для подтверждения вашей новой сессии";
+"create_room_section_footer_type_restricted" = "Все в пространстве могут искать и вступать.";
+"launch_loading_delay_warning" = "Это может занимать больше времени.\nСпасибо за терпение.";
diff --git a/Riot/Assets/sk.lproj/Vector.strings b/Riot/Assets/sk.lproj/Vector.strings
index 91e52cee0..061991f16 100644
--- a/Riot/Assets/sk.lproj/Vector.strings
+++ b/Riot/Assets/sk.lproj/Vector.strings
@@ -2960,3 +2960,8 @@
"room_command_change_display_name_description" = "Mení vaše zobrazované meno / prezývku";
"notice_display_name_changed_to" = "%@ zmenil/a svoje zobrazované meno na %@";
"poll_timeline_loading" = "Načítavanie…";
+"room_creation_user_not_found_prompt_title" = "Potvrdenie";
+"room_creation_user_not_found_prompt_invite_action" = "Spustiť konverzáciu aj tak";
+"room_participants_invite_anyway" = "Napriek tomu pozvať";
+"room_creation_user_not_found_prompt_message" = "Nie je možné nájsť používateľské profily pre toto Matrix ID. Chcete aj tak poslať priamu správu?";
+"room_participants_invite_unknown_participant_prompt_to_msg" = "Nie je možné nájsť profily pre toto Matrix ID. Ste si istí, že chcete pozvať %@ do %@?";
diff --git a/Riot/Assets/sv.lproj/Vector.strings b/Riot/Assets/sv.lproj/Vector.strings
index bbb4b12c5..48d13aea8 100644
--- a/Riot/Assets/sv.lproj/Vector.strings
+++ b/Riot/Assets/sv.lproj/Vector.strings
@@ -2676,3 +2676,31 @@
"room_command_change_room_topic_description" = "Sätter rummets ämne";
"room_command_discard_session_description" = "Tvingar den aktuella utgående gruppsessionen i ett krypterat rum att kasseras";
"room_command_error_unknown_command" = "Ogiltigt eller obehandlat kommando";
+
+// Legacy to Rust security upgrade
+
+"key_verification_self_verify_security_upgrade_alert_title" = "App uppdaterad";
+"key_verification_self_verify_security_upgrade_alert_message" = "Säker meddelandehantering har förbättrats med den senaste uppdateringen. Vänligen verifiera din enhet igen.";
+"device_verification_self_verify_open_on_other_device_title" = "Öppna %@ på din andra enhet";
+"device_verification_self_verify_wait_recover_secrets_additional_help" = "Kan du inte komma åt en befintlig %@-session?";
+"key_verification_scan_qr_code_title" = "Skanna QR-kod";
+"device_verification_self_verify_open_on_other_device_information" = "Du behöver verifiera den här sessionen för att kunna läsa din säkra meddelandehistorik.\n\nÖppna Element på en av dina andra enheter och följ instruktionerna.";
+"key_verification_scan_qr_code_information_other_user" = "Rikta kameran mot QR-koden som visas på deras enhet för att verifiera deras session";
+"room_waiting_other_participants_title" = "Väntar på att användare ska gå med i %@";
+"pill_message_from" = "Meddelande från %@";
+"pill_message_in" = "Meddelande i %@";
+"notice_display_name_changed_to" = "%@ bytte sitt visningsnamn till %@";
+
+// MARK: - Launch loading
+
+"launch_loading_generic" = "Synkar dina konversationer";
+"launch_loading_delay_warning" = "Detta kan ta lite längre tid.\nTack för ditt tålamod.";
+"key_verification_scan_qr_code_information_other_device" = "Rikta kameran mot QR-koden som visas på din andra enhet för att verifiera den här sessionen";
+"room_waiting_other_participants_message" = "När inbjudna användare har gått med i %@ kommer du att kunna chatta och rummet kommer att totalsträckskrypteras";
+"poll_timeline_loading" = "Laddar …";
+
+// Pills
+"pill_room_fallback_display_name" = "Utrymme/rum";
+"pill_message" = "Meddelande";
+"key_verification_scan_qr_code_information_new_session" = "Rikta kameran mot QR-koden som visas på din andra enhet för att verifiera din nya session";
+"key_verification_scan_qr_code_information_other_session" = "Rikta kameran mot QR-koden som visas på din andra enhet för att verifiera din session";
diff --git a/Riot/Assets/uk.lproj/Vector.strings b/Riot/Assets/uk.lproj/Vector.strings
index bac3f4c30..d5113e3c7 100644
--- a/Riot/Assets/uk.lproj/Vector.strings
+++ b/Riot/Assets/uk.lproj/Vector.strings
@@ -184,7 +184,7 @@
"settings_remove_prompt_title" = "Підтвердження";
"settings_surname" = "Прізвище";
"settings_first_name" = "Ім’я";
-"settings_display_name" = "Показуване ім’я";
+"settings_display_name" = "Псевдонім";
"settings_profile_picture" = "Зображення профілю";
"settings_sign_out_e2e_warn" = "Ви втратите всі ваші ключі наскрізного шифрування. Це означає що ви більше не будете мати змогу читати старі повідомлення у зашифрованих кімнатах на цьому пристрої.";
"settings_sign_out_confirmation" = "Ви впевнені?";
@@ -433,7 +433,7 @@
"room_widget_permission_theme_permission" = "Ваша тема";
"room_widget_permission_user_id_permission" = "Ваш ID користувача";
"room_widget_permission_avatar_url_permission" = "URL-адреса вашого аватара";
-"room_widget_permission_display_name_permission" = "Ваше показуване імʼя";
+"room_widget_permission_display_name_permission" = "Ваш псевдонім";
"room_widget_permission_creator_info_title" = "Цей віджет додано:";
// Room widget permissions
@@ -1129,7 +1129,7 @@
"settings_show_url_previews" = "Попередній перегляд вебсайтів";
"settings_ui_theme_picker_message_match_system_theme" = "«Авто» застосовує тему вашого пристрою";
"settings_ui_theme_picker_message_invert_colours" = "«Авто» застосовує налаштування вашого пристрою «Інвертувати кольори»";
-"settings_messages_containing_display_name" = "Моє показуване імʼя";
+"settings_messages_containing_display_name" = "Мій псевдонім";
"settings_discovery_three_pid_details_title_phone_number" = "Керувати номером телефону";
"settings_discovery_three_pid_details_title_email" = "Керувати е-поштою";
"settings_discovery_error_message" = "Сталася помилка. Повторіть спробу.";
@@ -1866,7 +1866,7 @@
"login_prompt_email_token" = "Введіть ключ підтвердження електронної пошти:";
"login_email_placeholder" = "Адреса е-пошти";
"login_email_info" = "Вкажіть адресу електронної пошти, щоб інші користувачі могли легше знаходити вас на Matrix і надання вам можливості відновити пароль у майбутньому.";
-"login_display_name_placeholder" = "Видиме ім'я (наприклад Bob Obson)";
+"login_display_name_placeholder" = "Псевдонім (наприклад Bob Obson)";
"login_optional_field" = "необов'язково";
"login_password_placeholder" = "Пароль";
"login_user_id_placeholder" = "Ідентифікатор Matrix (наприклад @bob:matrix.org або bob)";
@@ -2113,10 +2113,10 @@
"notice_room_history_visible_to_members_from_joined_point_for_dm" = "%@ робить майбутню історію повідомлень видимою всім від часу їхнього приєднання.";
"notice_room_history_visible_to_members_from_joined_point" = "%@ робить майбутню історію кімнати видимою всім учасникам кімнати від часу їхнього приєднання.";
"notice_room_history_visible_to_members_from_invited_point_for_dm" = "%@ робить майбутню історію повідомлень видимою всім від часу їхнього запрошення.";
-"notice_room_history_visible_to_members_from_invited_point" = "%@ робить майбутню історію кімнати видимою усім учасникам кімнати від часу їхнього запрошення.";
-"notice_room_history_visible_to_members_for_dm" = "%@ робить майбутню історію повідомлень видимою усім учасникам кімнати.";
-"notice_room_history_visible_to_members" = "%@ робить майбутню історію кімнати видимою усім учасникам кімнати.";
-"notice_room_history_visible_to_anyone" = "%@ робить майбутню історію кімнати видимою усім.";
+"notice_room_history_visible_to_members_from_invited_point" = "%@ робить майбутню історію кімнати видимою всім учасникам кімнати від часу їхнього запрошення.";
+"notice_room_history_visible_to_members_for_dm" = "%@ робить майбутню історію повідомлень видимою всім учасникам кімнати.";
+"notice_room_history_visible_to_members" = "%@ робить майбутню історію кімнати видимою всім учасникам кімнати.";
+"notice_room_history_visible_to_anyone" = "%@ робить майбутню історію кімнати видимою всім.";
"notice_redaction" = "%@ редагує подію (id: %@)";
"notice_feedback" = "Подія відгуку (id: %@): %@";
"notice_room_related_groups" = "Групи пов'язані з цією кімнатою: %@";
@@ -2136,9 +2136,9 @@
"notice_room_name_changed_for_dm" = "%@ змінює назву на %@.";
"notice_room_name_changed" = "%@ змінює назву кімнати на %@.";
"notice_topic_changed" = "%@ змінює тему на «%@».";
-"notice_display_name_removed" = "%@ вилучає своє показуване ім'я";
-"notice_display_name_changed_from" = "%@ змінює своє показуване ім'я з %@ на %@";
-"notice_display_name_set" = "%@ встановлює своїм показуваним іменем %@";
+"notice_display_name_removed" = "%@ вилучає свій псевдонім";
+"notice_display_name_changed_from" = "%@ змінює свій псевдонім з %@ на %@";
+"notice_display_name_set" = "%@ встановлює своїм псевдонімом %@";
"notice_room_withdraw" = "%@ анульовує запрошення для %@";
"notice_room_kick" = "%@ вилучає %@";
"notice_room_reject" = "%@ відхиляє запрошення";
@@ -2194,7 +2194,7 @@
"notification_settings_per_room_notifications" = "Сповіщення від кожної кімнати";
"notification_settings_per_sender_notifications" = "Сповіщення про кожного відправника";
"notification_settings_contain_my_user_name" = "Сповіщати звуком про повідомлення, що містять моє ім'я користиувача";
-"notification_settings_contain_my_display_name" = "Сповіщати звуком про повідомлення, що містять моє показуване ім'я";
+"notification_settings_contain_my_display_name" = "Сповіщати звуком про повідомлення з моїм псевдонімом";
"notification_settings_just_sent_to_me" = "Сповіщати звуком про надіслані лише мені повідомлення";
"notification_settings_invite_to_a_new_room" = "Сповіщати про запрошення до нових кімнат";
"notification_settings_people_join_leave_rooms" = "Сповіщати, коли люди приєднуються чи виходять з кімнат";
@@ -2209,7 +2209,7 @@
"account_error_email_wrong_title" = "Неправильна адреса е-пошти";
"account_error_matrix_session_is_not_opened" = "Сеанс Matrix не відкрито";
"account_error_picture_change_failed" = "Не вдалося змінити зображення";
-"account_error_display_name_change_failed" = "Не вдалося змінити показуване ім'я";
+"account_error_display_name_change_failed" = "Не вдалося змінити псевдонім";
"account_msisdn_validation_error" = "Не вдалося перевірити номер телефону.";
"account_email_validation_title" = "Очікування перевірки";
"account_msisdn_validation_title" = "Очікування перевірки";
@@ -2241,12 +2241,12 @@
"e2e_passphrase_enter" = "Введіть парольну фразу";
"e2e_passphrase_empty" = "Парольна фраза не повинна бути порожньою";
"e2e_passphrase_confirm" = "Підтвердити парольну фразу";
-"notice_room_history_visible_to_members_from_joined_point_by_you_for_dm" = "Ви зробили майбутні повідомлення кімнати видимими будь-кому від часу їхнього приєднання.";
-"notice_room_history_visible_to_members_from_joined_point_by_you" = "Ви зробили майбутню історію кімнати видимою усім учасникам кімнати від часу їхнього приєднання.";
+"notice_room_history_visible_to_members_from_joined_point_by_you_for_dm" = "Ви зробили майбутні повідомлення кімнати видимими всім від часу їхнього приєднання.";
+"notice_room_history_visible_to_members_from_joined_point_by_you" = "Ви зробили майбутню історію кімнати видимою всім учасникам кімнати від часу їхнього приєднання.";
"notice_room_history_visible_to_members_from_invited_point_by_you_for_dm" = "Ви зробили майбутні повідомлення кімнати видимими будь-кому від часу запрошення їх.";
-"notice_room_history_visible_to_members_from_invited_point_by_you" = "Ви зробили майбутню історію кімнати видимою усім учасникам кімнати від часу запрошення їх.";
-"notice_room_history_visible_to_members_by_you_for_dm" = "Ви зробили майбутні повідомлення кімнати видимими усім учасникам кімнати.";
-"notice_room_history_visible_to_members_by_you" = "Ви зробили майбутню історію кімнати видимою усім учасникам кімнати.";
+"notice_room_history_visible_to_members_from_invited_point_by_you" = "Ви зробили майбутню історію кімнати видимою всім учасникам кімнати від часу запрошення їх.";
+"notice_room_history_visible_to_members_by_you_for_dm" = "Ви зробили майбутні повідомлення кімнати видимими всім учасникам кімнати.";
+"notice_room_history_visible_to_members_by_you" = "Ви зробили майбутню історію кімнати видимою всім учасникам кімнати.";
"notice_room_history_visible_to_anyone_by_you" = "Ви зробили майбутню історію кімнати видимою будь-кому.";
"notice_room_created_by_you" = "Ви створили й сконфігурували кімнату.";
"notice_profile_change_redacted_by_you" = "Ви оновили свій профіль %@";
@@ -2261,9 +2261,9 @@
"notice_room_name_changed_by_you_for_dm" = "Ви змінили назву на %@.";
"notice_room_name_changed_by_you" = "Ви змінили назву кімнати на %@.";
"notice_topic_changed_by_you" = "Ви змінили тему на «%@».";
-"notice_display_name_removed_by_you" = "Ви вилучили показуване ім'я";
-"notice_display_name_changed_from_by_you" = "Ви змінили показуване ім'я з %@ на %@";
-"notice_display_name_set_by_you" = "Ви вказали показуваним іменем %@";
+"notice_display_name_removed_by_you" = "Ви вилучили псевдонім";
+"notice_display_name_changed_from_by_you" = "Ви змінили псевдонім з %@ на %@";
+"notice_display_name_set_by_you" = "Ви налаштували псевдонімом %@";
"notice_conference_call_finished" = "Голосовий груповий виклик завершено";
"notice_conference_call_started" = "Груповий голосовий виклик розпочато";
"notice_conference_call_request" = "%@ запрошує до групового голосового виклику";
@@ -2467,11 +2467,11 @@
"onboarding_avatar_accessibility_label" = "Зображення профілю";
"onboarding_avatar_message" = "Час додати обличчя до імені";
"onboarding_avatar_title" = "Додати зображення профілю";
-"onboarding_display_name_max_length" = "Ваше показуване ім'я повинно складатися з менш ніж 256 символів";
+"onboarding_display_name_max_length" = "Ваш псевдонім повинен складатися з менш ніж 256 символів";
"onboarding_display_name_hint" = "Ви можете змінити його пізніше";
-"onboarding_display_name_placeholder" = "Показуване ім'я";
+"onboarding_display_name_placeholder" = "Псевдонім";
"onboarding_display_name_message" = "Його буде показано у надісланих повідомленнях.";
-"onboarding_display_name_title" = "Виберіть показуване ім'я";
+"onboarding_display_name_title" = "Оберіть псевдонім";
"onboarding_personalization_skip" = "Пропустити цей крок";
"onboarding_personalization_save" = "Зберегти й продовжити";
"onboarding_congratulations_home_button" = "На головну";
@@ -2960,5 +2960,10 @@
// Room commands descriptions
"room_command_change_display_name_description" = "Змінює ваш нік";
-"notice_display_name_changed_to" = "%@ змінили своє показуване ім'я на %@";
+"notice_display_name_changed_to" = "%@ змінили свій псевдонім на %@";
"poll_timeline_loading" = "Завантаження...";
+"room_creation_user_not_found_prompt_invite_action" = "Усе одно розпочати приватну бесіду";
+"room_participants_invite_anyway" = "Усе одно запросити";
+"room_creation_user_not_found_prompt_title" = "Підтвердження";
+"room_creation_user_not_found_prompt_message" = "Не вдалося знайти профілі для цього Matrix ID. Усе одно хочете розпочати приватну бесіду?";
+"room_participants_invite_unknown_participant_prompt_to_msg" = "Не вдалося знайти профілі для цього Matrix ID. Ви впевнені, що хочете запросити %@ до %@?";
diff --git a/Riot/Generated/BWIStrings.swift b/Riot/Generated/BWIStrings.swift
index 7c7d639fb..fc0327740 100644
--- a/Riot/Generated/BWIStrings.swift
+++ b/Riot/Generated/BWIStrings.swift
@@ -15,6 +15,10 @@ public class BWIL10n: NSObject {
public static var allChatsEditLayoutShowPersonalNotes: String {
return BWIL10n.tr("Bwi", "all_chats_edit_layout_show_personal_notes")
}
+ /// Suche
+ public static var allChatsSearchbarPrompt: String {
+ return BWIL10n.tr("Bwi", "all_chats_searchbar_prompt")
+ }
/// Passwort vergessen?
public static var authForgotPassword: String {
return BWIL10n.tr("Bwi", "auth_forgot_password")
@@ -207,6 +211,10 @@ public class BWIL10n: NSObject {
public static var bwiEditPersonalStateTitle: String {
return BWIL10n.tr("Bwi", "bwi_edit_personal_state_title")
}
+ /// Falsches Passwort
+ public static var bwiErrorInvalidPassword: String {
+ return BWIL10n.tr("Bwi", "bwi_error_invalid_password")
+ }
/// %@ ist bereits im Raum.
public static func bwiErrorInviteAlreadyInRoom(_ p1: String) -> String {
return BWIL10n.tr("Bwi", "bwi_error_invite_already_in_room", p1)
@@ -231,7 +239,7 @@ public class BWIL10n: NSObject {
public static var bwiErrorRoomNotAvailableTitle: String {
return BWIL10n.tr("Bwi", "bwi_error_room_not_available_title")
}
- /// Mit dem neuen Feature Ruhezeiteneinstellung lassen sich Benachrichtigungen nach Wochentag und Uhrzeit ein- bzw stummschalten.
+ /// Beim Schreiben von Nachrichten kannst Du jetzt sehr einfach Textformatierungen verwenden.
public static var bwiFeatureBannerAdvertisementText: String {
return BWIL10n.tr("Bwi", "bwi_feature_banner_advertisement_text")
}
@@ -527,10 +535,38 @@ public class BWIL10n: NSObject {
public static var bwiSettingsDeveloperApplyOrigAppConfig: String {
return BWIL10n.tr("Bwi", "bwi_settings_developer_apply_orig_app_config")
}
+ /// Capabilities
+ public static var bwiSettingsDeveloperCapabilities: String {
+ return BWIL10n.tr("Bwi", "bwi_settings_developer_capabilities")
+ }
/// Neuen Notizen-Raum Raum erstellen
public static var bwiSettingsDeveloperCreateNewPersonalNotesRoom: String {
return BWIL10n.tr("Bwi", "bwi_settings_developer_create_new_personal_notes_room")
}
+ /// Key Backup
+ public static var bwiSettingsDeveloperKeyBackup: String {
+ return BWIL10n.tr("Bwi", "bwi_settings_developer_key_backup")
+ }
+ /// Algorithmus
+ public static var bwiSettingsDeveloperKeyBackupAlgorithm: String {
+ return BWIL10n.tr("Bwi", "bwi_settings_developer_key_backup_algorithm")
+ }
+ /// Gespeicherte Schlüssel
+ public static var bwiSettingsDeveloperKeyBackupCount: String {
+ return BWIL10n.tr("Bwi", "bwi_settings_developer_key_backup_count")
+ }
+ /// ETag
+ public static var bwiSettingsDeveloperKeyBackupEtag: String {
+ return BWIL10n.tr("Bwi", "bwi_settings_developer_key_backup_etag")
+ }
+ /// Version
+ public static var bwiSettingsDeveloperKeyBackupVersion: String {
+ return BWIL10n.tr("Bwi", "bwi_settings_developer_key_backup_version")
+ }
+ /// Maintenance
+ public static var bwiSettingsDeveloperMaintenance: String {
+ return BWIL10n.tr("Bwi", "bwi_settings_developer_maintenance")
+ }
/// Der alte Notizen-Raum Raum wurde durch einen neuen ersetzt.
public static var bwiSettingsDeveloperNewPersonalNotesRoomCreated: String {
return BWIL10n.tr("Bwi", "bwi_settings_developer_new_personal_notes_room_created")
@@ -571,6 +607,18 @@ public class BWIL10n: NSObject {
public static var bwiSettingsDeveloperUnrestrictUser: String {
return BWIL10n.tr("Bwi", "bwi_settings_developer_unrestrict_user")
}
+ /// Account Data
+ public static var bwiSettingsDeveloperUserAccountData: String {
+ return BWIL10n.tr("Bwi", "bwi_settings_developer_user_account_data")
+ }
+ /// Type
+ public static var bwiSettingsDeveloperUserAccountDataType: String {
+ return BWIL10n.tr("Bwi", "bwi_settings_developer_user_account_data_type")
+ }
+ /// Well-Known
+ public static var bwiSettingsDeveloperWellKnown: String {
+ return BWIL10n.tr("Bwi", "bwi_settings_developer_well_known")
+ }
/// Einen Raum für private Notizen anzeigen
public static var bwiSettingsEnableNotesRoomSummary: String {
return BWIL10n.tr("Bwi", "bwi_settings_enable_notes_room_summary")
@@ -739,6 +787,10 @@ public class BWIL10n: NSObject {
public static var e2eKeyBackupWrongVersion: String {
return BWIL10n.tr("Bwi", "e2e_key_backup_wrong_version")
}
+ /// Notizen ausblenden
+ public static var homeContextMenuPersonalNotes: String {
+ return BWIL10n.tr("Bwi", "home_context_menu_personal_notes")
+ }
/// Die Verbindung zum Heimserver ist fehlgeschlagen.
public static var homeserverConnectionLost: String {
return BWIL10n.tr("Bwi", "homeserver_connection_lost")
@@ -1011,6 +1063,14 @@ public class BWIL10n: NSObject {
public static var pollEditFormPollTypeOpen: String {
return BWIL10n.tr("Bwi", "poll_edit_form_poll_type_open")
}
+ /// Uhr
+ public static var pollParticipantDetailsClockString: String {
+ return BWIL10n.tr("Bwi", "poll_participant_details_clock_string")
+ }
+ /// Heute,
+ public static var pollParticipantDetailsDateStringToday: String {
+ return BWIL10n.tr("Bwi", "poll_participant_details_date_string_today")
+ }
/// Alle ansehen (%lu weitere)
public static func pollParticipantDetailsShowMore(_ p1: Int) -> String {
return BWIL10n.tr("Bwi", "poll_participant_details_show_more", p1)
@@ -1019,7 +1079,7 @@ public class BWIL10n: NSObject {
public static var pollParticipantDetailsTitle: String {
return BWIL10n.tr("Bwi", "poll_participant_details_title")
}
- /// Stimmen anzeigen
+ /// Stimmen ansehen
public static var pollTimelineShowParticipantsButton: String {
return BWIL10n.tr("Bwi", "poll_timeline_show_participants_button")
}
@@ -1587,6 +1647,10 @@ public class BWIL10n: NSObject {
public static var settingsOther: String {
return BWIL10n.tr("Bwi", "settings_other")
}
+ /// Dein Passwort wurde erfolgreich geändert.
+ public static var settingsPasswordChanged: String {
+ return BWIL10n.tr("Bwi", "settings_password_changed")
+ }
/// Regeln: Mindestlänge 8 Zeichen, mind. 1 Sonderzeichen, 1 Groß- und 1 Kleinbuchstaben und 1 Ziffer
public static var settingsPasswordCondition: String {
return BWIL10n.tr("Bwi", "settings_password_condition")
@@ -1611,10 +1675,6 @@ public class BWIL10n: NSObject {
public static var settingsPasswordTooShortMessage: String {
return BWIL10n.tr("Bwi", "settings_password_too_short_message")
}
- /// Dein Passwort wurde aktualisiert
- public static var settingsPasswordUpdated: String {
- return BWIL10n.tr("Bwi", "settings_password_updated")
- }
/// Permalink Prefix
public static var settingsPermalinkPrefixPickerTitle: String {
return BWIL10n.tr("Bwi", "settings_permalink_prefix_picker_title")
@@ -1755,7 +1815,7 @@ public class BWIL10n: NSObject {
public static func voiceMessageRemainingRecordingTime(_ p1: String) -> String {
return BWIL10n.tr("Bwi", "voice_message_remaining_recording_time", p1)
}
- /// Sliden zum Abbrechen
+ /// Wischen zum Abbrechen
public static var voiceMessageSlideToCancel: String {
return BWIL10n.tr("Bwi", "voice_message_slide_to_cancel")
}
diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift
index c59cb5e4d..b446b0823 100644
--- a/Riot/Generated/Strings.swift
+++ b/Riot/Generated/Strings.swift
@@ -215,7 +215,7 @@ public class VectorL10n: NSObject {
public static var allChatsSectionTitle: String {
return VectorL10n.tr("Vector", "all_chats_section_title")
}
- /// All chats
+ /// Chats
public static var allChatsTitle: String {
return VectorL10n.tr("Vector", "all_chats_title")
}
@@ -3667,6 +3667,14 @@ public class VectorL10n: NSObject {
public static var manageSessionNotTrusted: String {
return VectorL10n.tr("Vector", "manage_session_not_trusted")
}
+ /// You will be redirected to your server's authentication provider to complete sign out.
+ public static var manageSessionRedirect: String {
+ return VectorL10n.tr("Vector", "manage_session_redirect")
+ }
+ /// Functionality currently unavailable. Please contact your homeserver admin
+ public static var manageSessionRedirectError: String {
+ return VectorL10n.tr("Vector", "manage_session_redirect_error")
+ }
/// Rename session
public static var manageSessionRename: String {
return VectorL10n.tr("Vector", "manage_session_rename")
@@ -7791,6 +7799,18 @@ public class VectorL10n: NSObject {
public static var settingsLinks: String {
return VectorL10n.tr("Vector", "settings_links")
}
+ /// Manage account
+ public static var settingsManageAccountAction: String {
+ return VectorL10n.tr("Vector", "settings_manage_account_action")
+ }
+ /// Manage your account at %@
+ public static func settingsManageAccountDescription(_ p1: String) -> String {
+ return VectorL10n.tr("Vector", "settings_manage_account_description", p1)
+ }
+ /// Account
+ public static var settingsManageAccountTitle: String {
+ return VectorL10n.tr("Vector", "settings_manage_account_title")
+ }
/// Mark all messages as read
public static var settingsMarkAllAsRead: String {
return VectorL10n.tr("Vector", "settings_mark_all_as_read")
diff --git a/Riot/Managers/Settings/RiotSettings.swift b/Riot/Managers/Settings/RiotSettings.swift
index 05734cc4d..f02377f34 100644
--- a/Riot/Managers/Settings/RiotSettings.swift
+++ b/Riot/Managers/Settings/RiotSettings.swift
@@ -192,7 +192,7 @@ final class RiotSettings: NSObject {
var enableClientInformationFeature
/// Flag indicating if the wysiwyg composer feature is enabled
- @UserDefault(key: "enableWysiwygComposer", defaultValue: false, storage: defaults)
+ @UserDefault(key: "enableWysiwygComposer", defaultValue: BWIBuildSettings.shared.enableFeatureWYSIWYGByDefault, storage: defaults)
var enableWysiwygComposer
@UserDefault(key: "enableWysiwygTextFormatting", defaultValue: true, storage: defaults)
diff --git a/Riot/Model/HomeserverConfiguration/HomeserverConfigurationBuilder.swift b/Riot/Model/HomeserverConfiguration/HomeserverConfigurationBuilder.swift
index f1f409f65..24dfe5c78 100644
--- a/Riot/Model/HomeserverConfiguration/HomeserverConfigurationBuilder.swift
+++ b/Riot/Model/HomeserverConfiguration/HomeserverConfigurationBuilder.swift
@@ -52,11 +52,14 @@ final class HomeserverConfigurationBuilder: NSObject {
} else {
secureBackupSetupMethods = [.passphrase]
}
+
+ let deviceDehydrationEnabled = wellKnown?.jsonDictionary()["org.matrix.msc3814"] as? Bool == true
let encryptionConfiguration = HomeserverEncryptionConfiguration(isE2EEByDefaultEnabled: isE2EEByDefaultEnabled,
isSecureBackupRequired: isSecureBackupRequired,
secureBackupSetupMethods: secureBackupSetupMethods,
- outboundKeysPreSharingMode: outboundKeysPreSharingMode)
+ outboundKeysPreSharingMode: outboundKeysPreSharingMode,
+ deviceDehydrationEnabled: deviceDehydrationEnabled)
// Jitsi configuration
let jitsiPreferredDomain: String?
diff --git a/Riot/Model/HomeserverConfiguration/HomeserverEncryptionConfiguration.swift b/Riot/Model/HomeserverConfiguration/HomeserverEncryptionConfiguration.swift
index 6672bff45..671756f63 100644
--- a/Riot/Model/HomeserverConfiguration/HomeserverEncryptionConfiguration.swift
+++ b/Riot/Model/HomeserverConfiguration/HomeserverEncryptionConfiguration.swift
@@ -23,15 +23,18 @@ final class HomeserverEncryptionConfiguration: NSObject {
let isSecureBackupRequired: Bool
let secureBackupSetupMethods: [VectorWellKnownBackupSetupMethod]
let outboundKeysPreSharingMode: MXKKeyPreSharingStrategy
+ let deviceDehydrationEnabled: Bool
init(isE2EEByDefaultEnabled: Bool,
isSecureBackupRequired: Bool,
secureBackupSetupMethods: [VectorWellKnownBackupSetupMethod],
- outboundKeysPreSharingMode: MXKKeyPreSharingStrategy) {
+ outboundKeysPreSharingMode: MXKKeyPreSharingStrategy,
+ deviceDehydrationEnabled: Bool) {
self.isE2EEByDefaultEnabled = isE2EEByDefaultEnabled
self.isSecureBackupRequired = isSecureBackupRequired
self.outboundKeysPreSharingMode = outboundKeysPreSharingMode
self.secureBackupSetupMethods = secureBackupSetupMethods
+ self.deviceDehydrationEnabled = deviceDehydrationEnabled
super.init()
}
diff --git a/Riot/Modules/Authentication/AuthenticationCoordinator.swift b/Riot/Modules/Authentication/AuthenticationCoordinator.swift
index cb10aacfd..05b80ca30 100644
--- a/Riot/Modules/Authentication/AuthenticationCoordinator.swift
+++ b/Riot/Modules/Authentication/AuthenticationCoordinator.swift
@@ -144,7 +144,12 @@ final class AuthenticationCoordinator: NSObject, AuthenticationCoordinatorProtoc
// bwi: force serverselection on test apps
if (BWIBuildSettings.shared.authScreenShowTestServerOptions && BWIBuildSettings.shared.bwiLoginFlowLayout) ||
BWIBuildSettings.shared.bumLoginFlowLayout {
- showServerSelectionScreen(for: flow)
+ // bwi #3811: when there is a valid url from app config don't show server selection
+ if BWIBuildSettings.shared.avoidServerSelectionOnAppConfig && AppConfigService.shared.isAppConfig {
+ self.useHomeserver(AppConfigService.shared.serverUrl())
+ } else {
+ showServerSelectionScreen(for: flow)
+ }
} else {
do {
// Start the flow using the default server (or a provisioning link if set).
@@ -267,6 +272,21 @@ final class AuthenticationCoordinator: NSObject, AuthenticationCoordinatorProtoc
callback?(.cancel(.register))
}
+ /// Updates the login flow using the supplied homeserver address, or shows an error when this isn't possible.
+ @MainActor private func useHomeserver(_ homeserverAddress: String) {
+
+ let homeserverAddress = HomeserverAddress.sanitized(homeserverAddress)
+
+ Task {
+ do {
+ try await authenticationService.startFlow(.login, for: homeserverAddress)
+ showLoginScreen()
+ } catch {
+ displayError(message: error.localizedDescription)
+ }
+ }
+ }
+
// MARK: - Login
/// Shows the login screen.
diff --git a/Riot/Modules/Authentication/SSO/SSOAuthenticationService.swift b/Riot/Modules/Authentication/SSO/SSOAuthenticationService.swift
index a0282c742..706c3782d 100644
--- a/Riot/Modules/Authentication/SSO/SSOAuthenticationService.swift
+++ b/Riot/Modules/Authentication/SSO/SSOAuthenticationService.swift
@@ -50,7 +50,7 @@ final class SSOAuthenticationService: NSObject {
var ssoRedirectPath = SSOURLConstants.Paths.redirect
- if let identityProvider = identityProvider {
+ if let identityProvider = identityProvider, !identityProvider.isEmpty {
ssoRedirectPath.append("/\(identityProvider)")
}
diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m
index 3170fc2df..fffaa3fe3 100644
--- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m
+++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m
@@ -129,23 +129,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
}
- (NSArray.*
(.*
}
case MXEventTypeRoomCreate:
{
- NSString *creatorId;
- MXJSONModelSetString(creatorId, event.content[@"creator"]);
+ // Room version 11 removes `creator` in favour of `sender`.
+ // https://github.com/matrix-org/matrix-spec-proposals/pull/2175
+ // Just use the sender as it is possible to create a v11 room and spoof the `creator`.
+ NSString *creatorId = event.sender;
- if (creatorId)
+ if ([creatorId isEqualToString:mxSession.myUserId])
{
- if ([creatorId isEqualToString:mxSession.myUserId])
+ if (isRoomDirect)
{
- if (isRoomDirect)
- {
- displayText = [VectorL10n noticeRoomCreatedByYouForDm];
- }
- else
- {
- displayText = [VectorL10n noticeRoomCreatedByYou];
- }
+ displayText = [VectorL10n noticeRoomCreatedByYouForDm];
}
else
{
- if (isRoomDirect)
- {
- displayText = [VectorL10n noticeRoomCreatedForDm:(roomState ? [roomState.members memberName:creatorId] : creatorId)];
- }
- else
- {
- displayText = [VectorL10n noticeRoomCreated:(roomState ? [roomState.members memberName:creatorId] : creatorId)];
- }
+ displayText = [VectorL10n noticeRoomCreatedByYou];
}
- // Append redacted info if any
- if (redactedInfo)
+ }
+ else
+ {
+ if (isRoomDirect)
{
- displayText = [NSString stringWithFormat:@"%@ %@", displayText, redactedInfo];
+ displayText = [VectorL10n noticeRoomCreatedForDm:(roomState ? [roomState.members memberName:creatorId] : creatorId)];
}
+ else
+ {
+ displayText = [VectorL10n noticeRoomCreated:(roomState ? [roomState.members memberName:creatorId] : creatorId)];
+ }
+ }
+ // Append redacted info if any
+ if (redactedInfo)
+ {
+ displayText = [NSString stringWithFormat:@"%@ %@", displayText, redactedInfo];
}
break;
}
diff --git a/Riot/Modules/Onboarding/OnboardingCoordinator.swift b/Riot/Modules/Onboarding/OnboardingCoordinator.swift
index 7e17b32ad..ef638a2c2 100644
--- a/Riot/Modules/Onboarding/OnboardingCoordinator.swift
+++ b/Riot/Modules/Onboarding/OnboardingCoordinator.swift
@@ -189,7 +189,7 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol {
}
private func showWelcomeExperience() {
- let welcomeVC = WelcomeExperienceViewController.makeViewController(completion: { [weak self] in
+ let welcomeVC = WelcomeExperienceViewController.makeViewController(completion: { [weak self] in
if BWIBuildSettings.shared.onboardingEnableNewAuthenticationFlow {
self?.startLoading()
self?.beginAuthentication(with: .login) { [weak self] in
diff --git a/Riot/Modules/Pills/PillsFormatter.swift b/Riot/Modules/Pills/PillsFormatter.swift
index 1b6256835..ecdfac5fe 100644
--- a/Riot/Modules/Pills/PillsFormatter.swift
+++ b/Riot/Modules/Pills/PillsFormatter.swift
@@ -197,12 +197,14 @@ class PillsFormatter: NSObject {
guard let roomMember = roomState.members.member(withUserId: userId) else {
return
}
+
+ let displayName = roomMember.displayname ?? userId
pill.data?.items = [
.avatar(url: roomMember.avatarUrl,
- string: roomMember.displayname,
- matrixId: roomMember.userId),
- .text(roomMember.displayname)
+ string: displayName,
+ matrixId: userId),
+ .text(displayName)
]
default:
break
diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m
index 9e33cee1d..a714b0a4e 100644
--- a/Riot/Modules/Room/RoomViewController.m
+++ b/Riot/Modules/Room/RoomViewController.m
@@ -4108,8 +4108,10 @@ static CGSize kThreadListBarButtonItemImageSize;
[self cancelEventSelection];
}]];
}
-
- if (!isJitsiCallEvent && !selectedEvent.isTimelinePollEvent &&
+
+ // bwi: #5160 disable quote function for new wysiwyg composer because it does not work
+ if (!([RoomViewController mainToolbarClass] == WysiwygInputToolbarView.class) &&
+ !isJitsiCallEvent && !selectedEvent.isTimelinePollEvent &&
selectedEvent.eventType != MXEventTypeBeaconInfo)
{
[self.eventMenuBuilder addItemWithType:EventMenuItemTypeQuote
diff --git a/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift b/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift
index edd951fd6..f3b4d0bb7 100644
--- a/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift
+++ b/Riot/Modules/Room/Views/WYSIWYGInputToolbar/WysiwygInputToolbarView.swift
@@ -207,8 +207,14 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp
}
func mention(_ member: MXRoomMember) {
- self.wysiwygViewModel.setMention(url: MXTools.permalinkToUser(withUserId: member.userId),
- name: member.displayname,
+ guard let userId = member.userId else {
+ return
+ }
+
+ let displayName = member.displayname ?? userId
+
+ self.wysiwygViewModel.setMention(url: MXTools.permalinkToUser(withUserId: userId),
+ name: displayName,
mentionType: .user)
}
@@ -373,7 +379,8 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp
}
private func sendWysiwygMessage(content: WysiwygComposerContent) {
- if content.markdown.prefix(while: { $0 == "/" }).count == 1 {
+ // bwi: #4955 disable WYSIWYG commands
+ if BWIBuildSettings.shared.enableWYSIWYGCommands && content.markdown.prefix(while: { $0 == "/" }).count == 1 {
let commandText: String
if content.markdown.hasPrefix(MXKSlashCommand.emote.cmd) {
// `/me` command works with markdown content
diff --git a/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.swift b/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.swift
index e26439230..350ce3e94 100644
--- a/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.swift
+++ b/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.swift
@@ -134,6 +134,8 @@ class VoiceMessageToolbarView: PassthroughView, NibLoadable, Themable, UIGesture
self.tapGesture = tapGesture
primaryRecordButton.accessibilityLabel = VectorL10n.roomAccessibilityRecordVoiceMessage
primaryRecordButton.accessibilityHint = VectorL10n.roomAccessibilityRecordVoiceMessageHint
+ // bwi: #5017 translate voice message cancel text
+ slideToCancelLabel.text = BWIL10n.voiceMessageSlideToCancel
updateUIWithDetails(VoiceMessageToolbarViewDetails(), animated: false)
}
diff --git a/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyCoordinator.swift b/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyCoordinator.swift
index 5d883def2..4f6f48e99 100644
--- a/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyCoordinator.swift
+++ b/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyCoordinator.swift
@@ -35,9 +35,9 @@ final class SecretsRecoveryWithKeyCoordinator: SecretsRecoveryWithKeyCoordinator
// MARK: - Setup
- init(recoveryService: MXRecoveryService, recoveryGoal: SecretsRecoveryGoal, cancellable: Bool) {
+ init(recoveryService: MXRecoveryService, recoveryGoal: SecretsRecoveryGoal, cancellable: Bool, dehydrationService: DehydrationService?) {
- let secretsRecoveryWithKeyViewModel = SecretsRecoveryWithKeyViewModel(recoveryService: recoveryService, recoveryGoal: recoveryGoal)
+ let secretsRecoveryWithKeyViewModel = SecretsRecoveryWithKeyViewModel(recoveryService: recoveryService, recoveryGoal: recoveryGoal, dehydrationService: dehydrationService)
let secretsRecoveryWithKeyViewController = SecretsRecoveryWithKeyViewController.instantiate(with: secretsRecoveryWithKeyViewModel, cancellable: cancellable)
self.secretsRecoveryWithKeyViewController = secretsRecoveryWithKeyViewController
self.secretsRecoveryWithKeyViewModel = secretsRecoveryWithKeyViewModel
diff --git a/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyViewModel.swift b/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyViewModel.swift
index f56562f7d..c18222bd0 100644
--- a/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyViewModel.swift
+++ b/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyViewModel.swift
@@ -24,6 +24,8 @@ final class SecretsRecoveryWithKeyViewModel: SecretsRecoveryWithKeyViewModelType
private let recoveryService: MXRecoveryService
+ private let dehydrationService: DehydrationService?
+
// MARK: Public
let recoveryGoal: SecretsRecoveryGoal
@@ -39,8 +41,9 @@ final class SecretsRecoveryWithKeyViewModel: SecretsRecoveryWithKeyViewModelType
// MARK: - Setup
- init(recoveryService: MXRecoveryService, recoveryGoal: SecretsRecoveryGoal) {
+ init(recoveryService: MXRecoveryService, recoveryGoal: SecretsRecoveryGoal, dehydrationService: DehydrationService?) {
self.recoveryService = recoveryService
+ self.dehydrationService = dehydrationService
self.recoveryGoal = recoveryGoal
}
@@ -83,6 +86,10 @@ final class SecretsRecoveryWithKeyViewModel: SecretsRecoveryWithKeyViewModelType
}
self.update(viewState: .loaded)
self.coordinatorDelegate?.secretsRecoveryWithKeyViewModelDidRecover(self)
+
+ Task {
+ await self.dehydrationService?.runDeviceDehydrationFlow(privateKeyData: privateKey)
+ }
}, failure: { [weak self] error in
guard let self = self else {
return
diff --git a/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseCoordinator.swift b/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseCoordinator.swift
index 3c0ad1dc3..a53929d12 100644
--- a/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseCoordinator.swift
+++ b/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseCoordinator.swift
@@ -35,8 +35,8 @@ final class SecretsRecoveryWithPassphraseCoordinator: SecretsRecoveryWithPassphr
// MARK: - Setup
- init(recoveryService: MXRecoveryService, recoveryGoal: SecretsRecoveryGoal, cancellable: Bool) {
- let secretsRecoveryWithPassphraseViewModel = SecretsRecoveryWithPassphraseViewModel(recoveryService: recoveryService, recoveryGoal: recoveryGoal)
+ init(recoveryService: MXRecoveryService, recoveryGoal: SecretsRecoveryGoal, cancellable: Bool, dehydrationService: DehydrationService?) {
+ let secretsRecoveryWithPassphraseViewModel = SecretsRecoveryWithPassphraseViewModel(recoveryService: recoveryService, recoveryGoal: recoveryGoal, dehydrationService: dehydrationService)
let secretsRecoveryWithPassphraseViewController = SecretsRecoveryWithPassphraseViewController.instantiate(with: secretsRecoveryWithPassphraseViewModel, cancellable: cancellable)
self.secretsRecoveryWithPassphraseViewController = secretsRecoveryWithPassphraseViewController
self.secretsRecoveryWithPassphraseViewModel = secretsRecoveryWithPassphraseViewModel
diff --git a/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseViewModel.swift b/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseViewModel.swift
index 71e51e270..dd05f8425 100644
--- a/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseViewModel.swift
+++ b/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseViewModel.swift
@@ -24,6 +24,8 @@ final class SecretsRecoveryWithPassphraseViewModel: SecretsRecoveryWithPassphras
private let recoveryService: MXRecoveryService
+ private let dehydrationService: DehydrationService?
+
// MARK: Public
let recoveryGoal: SecretsRecoveryGoal
@@ -39,8 +41,9 @@ final class SecretsRecoveryWithPassphraseViewModel: SecretsRecoveryWithPassphras
// MARK: - Setup
- init(recoveryService: MXRecoveryService, recoveryGoal: SecretsRecoveryGoal) {
+ init(recoveryService: MXRecoveryService, recoveryGoal: SecretsRecoveryGoal, dehydrationService: DehydrationService?) {
self.recoveryService = recoveryService
+ self.dehydrationService = dehydrationService
self.recoveryGoal = recoveryGoal
}
@@ -103,6 +106,10 @@ final class SecretsRecoveryWithPassphraseViewModel: SecretsRecoveryWithPassphras
}
self.update(viewState: .loaded)
self.coordinatorDelegate?.secretsRecoveryWithPassphraseViewModelDidRecover(self)
+
+ Task {
+ await self.dehydrationService?.runDeviceDehydrationFlow(privateKeyData: privateKey)
+ }
}, failure: { [weak self] error in
guard let self = self else {
return
diff --git a/Riot/Modules/Secrets/Recover/SecretsRecoveryCoordinator.swift b/Riot/Modules/Secrets/Recover/SecretsRecoveryCoordinator.swift
index 593f10139..315e19721 100644
--- a/Riot/Modules/Secrets/Recover/SecretsRecoveryCoordinator.swift
+++ b/Riot/Modules/Secrets/Recover/SecretsRecoveryCoordinator.swift
@@ -86,14 +86,28 @@ final class SecretsRecoveryCoordinator: SecretsRecoveryCoordinatorType {
// MARK: - Private
+ private var dehydrationService: DehydrationService? {
+ if self.session.vc_homeserverConfiguration().encryption.deviceDehydrationEnabled {
+ return self.session.crypto.dehydrationService
+ }
+
+ return nil
+ }
+
private func createRecoverFromKeyCoordinator() -> SecretsRecoveryWithKeyCoordinator {
- let coordinator = SecretsRecoveryWithKeyCoordinator(recoveryService: self.session.crypto.recoveryService, recoveryGoal: self.recoveryGoal, cancellable: self.cancellable)
+ let coordinator = SecretsRecoveryWithKeyCoordinator(recoveryService: self.session.crypto.recoveryService,
+ recoveryGoal: self.recoveryGoal,
+ cancellable: self.cancellable,
+ dehydrationService: dehydrationService)
coordinator.delegate = self
return coordinator
}
private func createRecoverFromPassphraseCoordinator() -> SecretsRecoveryWithPassphraseCoordinator {
- let coordinator = SecretsRecoveryWithPassphraseCoordinator(recoveryService: self.session.crypto.recoveryService, recoveryGoal: self.recoveryGoal, cancellable: self.cancellable)
+ let coordinator = SecretsRecoveryWithPassphraseCoordinator(recoveryService: self.session.crypto.recoveryService,
+ recoveryGoal: self.recoveryGoal,
+ cancellable: self.cancellable,
+ dehydrationService: dehydrationService)
coordinator.delegate = self
return coordinator
}
diff --git a/Riot/Modules/Secrets/Setup/RecoveryKey/SecretsSetupRecoveryKeyCoordinator.swift b/Riot/Modules/Secrets/Setup/RecoveryKey/SecretsSetupRecoveryKeyCoordinator.swift
index 58ebf79ba..9dc055e49 100644
--- a/Riot/Modules/Secrets/Setup/RecoveryKey/SecretsSetupRecoveryKeyCoordinator.swift
+++ b/Riot/Modules/Secrets/Setup/RecoveryKey/SecretsSetupRecoveryKeyCoordinator.swift
@@ -42,8 +42,13 @@ final class SecretsSetupRecoveryKeyCoordinator: SecretsSetupRecoveryKeyCoordinat
passphrase: String?,
passphraseOnly: Bool,
allowOverwrite: Bool = false,
- cancellable: Bool) {
- let secretsSetupRecoveryKeyViewModel = SecretsSetupRecoveryKeyViewModel(recoveryService: recoveryService, passphrase: passphrase, passphraseOnly: passphraseOnly, allowOverwrite: allowOverwrite)
+ cancellable: Bool,
+ dehydrationService: DehydrationService?) {
+ let secretsSetupRecoveryKeyViewModel = SecretsSetupRecoveryKeyViewModel(recoveryService: recoveryService,
+ passphrase: passphrase,
+ passphraseOnly: passphraseOnly,
+ allowOverwrite: allowOverwrite,
+ dehydrationService: dehydrationService)
let secretsSetupRecoveryKeyViewController = SecretsSetupRecoveryKeyViewController.instantiate(with: secretsSetupRecoveryKeyViewModel, cancellable: cancellable)
self.secretsSetupRecoveryKeyViewModel = secretsSetupRecoveryKeyViewModel
self.secretsSetupRecoveryKeyViewController = secretsSetupRecoveryKeyViewController
diff --git a/Riot/Modules/Secrets/Setup/RecoveryKey/SecretsSetupRecoveryKeyViewModel.swift b/Riot/Modules/Secrets/Setup/RecoveryKey/SecretsSetupRecoveryKeyViewModel.swift
index af85b7eb7..c91cb6787 100644
--- a/Riot/Modules/Secrets/Setup/RecoveryKey/SecretsSetupRecoveryKeyViewModel.swift
+++ b/Riot/Modules/Secrets/Setup/RecoveryKey/SecretsSetupRecoveryKeyViewModel.swift
@@ -28,6 +28,7 @@ final class SecretsSetupRecoveryKeyViewModel: SecretsSetupRecoveryKeyViewModelTy
private let passphrase: String?
private let passphraseOnly: Bool
private let allowOverwrite: Bool
+ private let dehydrationService: DehydrationService?
// MARK: Public
@@ -36,11 +37,12 @@ final class SecretsSetupRecoveryKeyViewModel: SecretsSetupRecoveryKeyViewModelTy
// MARK: - Setup
- init(recoveryService: MXRecoveryService, passphrase: String?, passphraseOnly: Bool, allowOverwrite: Bool = false) {
+ init(recoveryService: MXRecoveryService, passphrase: String?, passphraseOnly: Bool, allowOverwrite: Bool = false, dehydrationService: DehydrationService?) {
self.recoveryService = recoveryService
self.passphrase = passphrase
self.passphraseOnly = passphraseOnly
self.allowOverwrite = allowOverwrite
+ self.dehydrationService = dehydrationService
}
// MARK: - Public
@@ -76,6 +78,10 @@ final class SecretsSetupRecoveryKeyViewModel: SecretsSetupRecoveryKeyViewModelTy
self.recoveryService.createRecovery(forSecrets: nil, withPassphrase: self.passphrase, createServicesBackups: true, success: { secretStorageKeyCreationInfo in
self.update(viewState: .recoveryCreated(secretStorageKeyCreationInfo.recoveryKey))
+
+ Task {
+ await self.dehydrationService?.runDeviceDehydrationFlow(privateKeyData: secretStorageKeyCreationInfo.privateKey)
+ }
}, failure: { error in
self.update(viewState: .error(error))
})
diff --git a/Riot/Modules/SecureBackup/Setup/SecureBackupSetupCoordinator.swift b/Riot/Modules/SecureBackup/Setup/SecureBackupSetupCoordinator.swift
index d58444206..b3a5b06d5 100644
--- a/Riot/Modules/SecureBackup/Setup/SecureBackupSetupCoordinator.swift
+++ b/Riot/Modules/SecureBackup/Setup/SecureBackupSetupCoordinator.swift
@@ -104,9 +104,22 @@ final class SecureBackupSetupCoordinator: SecureBackupSetupCoordinatorType {
introViewController.delegate = self
return introViewController
}
-
+
+ private var dehydrationService: DehydrationService? {
+ if self.session.vc_homeserverConfiguration().encryption.deviceDehydrationEnabled {
+ return self.session.crypto.dehydrationService
+ }
+
+ return nil
+ }
+
private func showSetupKey(passphraseOnly: Bool, passphrase: String? = nil) {
- let coordinator = SecretsSetupRecoveryKeyCoordinator(recoveryService: self.recoveryService, passphrase: passphrase, passphraseOnly: passphraseOnly, allowOverwrite: allowOverwrite, cancellable: self.cancellable)
+ let coordinator = SecretsSetupRecoveryKeyCoordinator(recoveryService: self.recoveryService,
+ passphrase: passphrase,
+ passphraseOnly: passphraseOnly,
+ allowOverwrite: allowOverwrite,
+ cancellable: self.cancellable,
+ dehydrationService: dehydrationService)
coordinator.delegate = self
coordinator.start()
diff --git a/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.m b/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.m
index 74128bff0..7b93bd843 100644
--- a/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.m
+++ b/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.m
@@ -676,6 +676,53 @@ enum {
}
- (void)removeDevice
+{
+ MXWellKnownAuthentication *authentication = self.mainSession.homeserverWellknown.authentication;
+ if (BWIBuildSettings.shared.isOIDCEnabled &&
+ authentication)
+ {
+ NSURL *logoutURL = [authentication getLogoutDeviceURLFromID:device.deviceId];
+ if (logoutURL)
+ {
+ [self removeDeviceRedirectWithURL:logoutURL];
+ }
+ else
+ {
+ [self showRemoveDeviceRedirectError];
+ }
+ }
+ else
+ {
+ [self removeDeviceThroughAPI];
+ }
+}
+
+-(void) removeDeviceRedirectWithURL: (NSURL * _Nonnull) url
+{
+ UIAlertController *alert = [UIAlertController alertControllerWithTitle: [VectorL10n manageSessionRedirect] message: nil preferredStyle:UIAlertControllerStyleAlert];
+
+ __weak typeof(self) weakSelf = self;
+ UIAlertAction *action = [UIAlertAction actionWithTitle:[VectorL10n ok]
+ style:UIAlertActionStyleDefault
+ handler: ^(UIAlertAction * action) {
+ [UIApplication.sharedApplication openURL:url options:@{} completionHandler:^(BOOL success) {
+ if (success && weakSelf)
+ {
+ [weakSelf withdrawViewControllerAnimated:YES completion:nil];
+ }
+ }];
+ }];
+ [alert addAction: action];
+ [self presentViewController:alert animated:YES completion:nil];
+}
+
+-(void) showRemoveDeviceRedirectError
+{
+ UIAlertController *alert = [UIAlertController alertControllerWithTitle: [VectorL10n manageSessionRedirectError] message: nil preferredStyle:UIAlertControllerStyleAlert];
+ [self presentViewController:alert animated:YES completion:nil];
+}
+
+-(void) removeDeviceThroughAPI
{
[self startActivityIndicator];
self.view.userInteractionEnabled = NO;
diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m
index 3d6002e74..66f8afe94 100644
--- a/Riot/Modules/Settings/SettingsViewController.m
+++ b/Riot/Modules/Settings/SettingsViewController.m
@@ -55,6 +55,7 @@ typedef NS_ENUM(NSUInteger, SECTION_TAG)
SECTION_TAG_USER_SETTINGS,
SECTION_TAG_NEW_FEATURES,
SECTION_TAG_LOCATION_SHARING,
+ SECTION_TAG_ACCOUNT,
SECTION_TAG_SENDING_MEDIA,
SECTION_TAG_LINKS,
SECTION_TAG_SECURITY,
@@ -171,7 +172,8 @@ typedef NS_ENUM(NSUInteger, USER_INTERFACE)
TIMELINE_USER_AVATAR_INDEX,
TIMELINE_ENTER_ROOM_INDEX,
USER_INTERFACE_LANGUAGE_INDEX,
- USER_INTERFACE_TIMELINE_STYLE_INDEX
+ USER_INTERFACE_TIMELINE_STYLE_INDEX,
+ PERSONAL_NOTES_INDEX
};
typedef NS_ENUM(NSUInteger, TIMELINE)
@@ -252,6 +254,11 @@ enum
OUTDATED_WARNING = 0
};
+typedef NS_ENUM(NSUInteger, ACCOUNT)
+{
+ ACCOUNT_MANAGE_INDEX = 0,
+};
+
typedef void (^blockSettingsViewController_onReadyToDestroy)(void);
#pragma mark - SettingsViewController
@@ -466,7 +473,11 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
[sectionUserSettings addRowWithTag: USER_SETTINGS_PHONENUMBERS_OFFSET + index];
}
}
- if (BWIBuildSettings.shared.settingsScreenAllowAddingEmailThreepids)
+ if (BWIBuildSettings.shared.settingsScreenAllowAddingEmailThreepids &&
+ BuildSettings.settingsScreenAllowAddingEmailThreepids &&
+ // If the threePidChanges is nil we assume the capability to be true
+ (!self.mainSession.homeserverCapabilities.threePidChanges ||
+ self.mainSession.homeserverCapabilities.threePidChanges.enabled))
{
[sectionUserSettings addRowWithTag:USER_SETTINGS_ADD_EMAIL_INDEX];
}
@@ -493,7 +504,19 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
[tmpSections addObject:sectionNewFeatures];
}
- if (BWIBuildSettings.shared.settingsScreenShowConfirmMediaSize)
+ NSString *manageAccountURL = self.mainSession.homeserverWellknown.authentication.account;
+ if (BWIBuildSettings.shared.isOIDCEnabled &&
+ manageAccountURL)
+ {
+ Section *account = [Section sectionWithTag: SECTION_TAG_ACCOUNT];
+ [account addRowWithTag:ACCOUNT_MANAGE_INDEX];
+ account.headerTitle = [VectorL10n settingsManageAccountTitle];
+ account.footerTitle = [VectorL10n settingsManageAccountDescription:manageAccountURL];
+ [tmpSections addObject:account];
+ }
+
+ if (BWIBuildSettings.shared.settingsScreenShowConfirmMediaSize &&
+ BuildSettings.settingsScreenShowConfirmMediaSize)
{
Section *sectionMedia = [Section sectionWithTag:SECTION_TAG_SENDING_MEDIA];
[sectionMedia addRowWithTag:SENDING_MEDIA_CONFIRM_SIZE];
@@ -644,6 +667,9 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
//[sectionUserInterface addRowWithTag:USER_INTERFACE_LANGUAGE_INDEX];
[sectionUserInterface addRowWithTag:USER_INTERFACE_THEME_INDEX];
+ if (BWIBuildSettings.shared.bwiPersonalNotesVisibilityInSettings) {
+ [sectionUserInterface addRowWithTag:PERSONAL_NOTES_INDEX];
+ }
sectionUserInterface = [self updateTimeLine:sectionUserInterface];
[tmpSections addObject: sectionUserInterface];
@@ -733,7 +759,11 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
{
[sectionAbout addRowWithTag:ABOUT_ACCEPTABLE_USE_INDEX];
}
- if (BWIBuildSettings.shared.applicationPrivacyPolicyUrlString.length)
+ if (self.mainSession.homeserverWellknown.dataPrivacyURL != nil && BWIBuildSettings.shared.bwiUseWellKnownPrivacyPolicyLink)
+ {
+ [sectionAbout addRowWithTag:ABOUT_PRIVACY_INDEX];
+ }
+ else if (BWIBuildSettings.shared.applicationPrivacyPolicyUrlString.length && !BWIBuildSettings.shared.bwiUseWellKnownPrivacyPolicyLink)
{
[sectionAbout addRowWithTag:ABOUT_PRIVACY_INDEX];
}
@@ -779,18 +809,17 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
[sectionLabs addRowWithTag:LABS_ENABLE_LIVE_LOCATION_SHARING];
*/
- if (BWIBuildSettings.shared.enableLabFeatureWYSIWYG) {
+ /* bwi: #4941 WYSIWYG is now live
if (@available(iOS 15.0, *))
{
[sectionLabs addRowWithTag:LABS_ENABLE_WYSIWYG_COMPOSER];
}
- }
+ */
- // bwi: disabled for our apps
- if (BWIBuildSettings.shared.enableLabFeatureVoiceBroadcasts)
+ /* bwi: #4941 disabled for our apps
{
[sectionLabs addRowWithTag:LABS_ENABLE_VOICE_BROADCAST];
- }
+ */
sectionLabs.headerTitle = [VectorL10n settingsLabs];
if (sectionLabs.hasAnyRows)
{
@@ -798,14 +827,15 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
}
}
- if (BWIBuildSettings.shared.settingsScreenAllowDeactivatingAccount)
+ if (BWIBuildSettings.shared.settingsScreenAllowDeactivatingAccount && !BWIBuildSettings.shared.isOIDCEnabled &&
+ BuildSettings.settingsScreenAllowDeactivatingAccount && !self.mainSession.homeserverWellknown.authentication)
{
Section *sectionDeactivate = [Section sectionWithTag:SECTION_TAG_DEACTIVATE_ACCOUNT];
[sectionDeactivate addRowWithTag:0];
sectionDeactivate.headerTitle = [VectorL10n settingsDeactivateMyAccount];
[tmpSections addObject:sectionDeactivate];
}
-
+
Section *sectionSignOut = [Section sectionWithTag:SECTION_TAG_SIGN_OUT];
[sectionSignOut addRowWithTag:0];
[tmpSections addObject:sectionSignOut];
@@ -2537,6 +2567,9 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
} else if (row == USER_INTERFACE_TIMELINE_STYLE_INDEX)
{
cell = [self buildMessageBubblesCellForTableView:tableView atIndexPath:indexPath];
+ } else if (row == PERSONAL_NOTES_INDEX)
+ {
+ cell = [self cellForPersonalNotesVisibility:tableView indexPath:indexPath row:row];
} else {
cell = [self cellForTimeline:tableView indexPath:indexPath row:row];
}
@@ -3113,6 +3146,17 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
cell = showSettingsBtnCell;
}
}
+ else if (section == SECTION_TAG_ACCOUNT)
+ {
+ switch (row)
+ {
+ case ACCOUNT_MANAGE_INDEX:
+ cell = [self getDefaultTableViewCell:tableView];
+ cell.textLabel.text = [VectorL10n settingsManageAccountAction];
+ [cell vc_setAccessoryDisclosureIndicatorWithCurrentTheme];
+ break;
+ }
+ }
return cell;
}
@@ -3375,7 +3419,14 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
}
else if (row == ABOUT_PRIVACY_INDEX)
{
- [[UIApplication sharedApplication] openURL:[NSURL URLWithString:BWIBuildSettings.shared.applicationPrivacyPolicyUrlString] options:@{} completionHandler:nil];
+ if (BWIBuildSettings.shared.bwiUseWellKnownPrivacyPolicyLink)
+ {
+ [[UIApplication sharedApplication] openURL:[NSURL URLWithString:self.mainSession.homeserverWellknown.dataPrivacyURL] options:@{} completionHandler:nil];
+ }
+ else
+ {
+ [[UIApplication sharedApplication] openURL:[NSURL URLWithString:BWIBuildSettings.shared.applicationPrivacyPolicyUrlString] options:@{} completionHandler:nil];
+ }
}
else if (row == ABOUT_ACCESSIBILITY_DECLARATION_INDEX)
{
@@ -3497,6 +3548,14 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
[self pushViewController:webViewViewController];
}
}
+ else if (section == SECTION_TAG_ACCOUNT)
+ {
+ switch(row) {
+ case ACCOUNT_MANAGE_INDEX:
+ [self onManageAccountTap];
+ break;
+ }
+ }
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
@@ -4435,6 +4494,14 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
}
}
+- (void)onManageAccountTap
+{
+ NSURL *url = [NSURL URLWithString: self.mainSession.homeserverWellknown.authentication.account];
+ if (url) {
+ [UIApplication.sharedApplication openURL:url options:@{} completionHandler:nil];
+ }
+}
+
- (void)showThemePicker
{
__weak typeof(self) weakSelf = self;
@@ -5359,6 +5426,24 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
[self updateSections];
}
+- (UITableViewCell*) cellForPersonalNotesVisibility:(UITableView*)tableView indexPath:(NSIndexPath*)indexPath row:(NSInteger)row {
+ MXKTableViewCellWithLabelAndSwitch* labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath];
+
+ labelAndSwitchCell.mxkLabel.text = [BWIL10n bwiSettingsEnableNotesRoomTitle];
+ labelAndSwitchCell.mxkSwitch.on = [[[PersonalNotesSettings alloc] init] personalNotesVisible];
+ labelAndSwitchCell.mxkSwitch.thumbTintColor = ThemeService.shared.theme.backgroundColor;
+ labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor;
+ labelAndSwitchCell.mxkSwitch.enabled = YES;
+ [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(togglePersonalNotesVisibility:) forControlEvents:UIControlEventTouchUpInside];
+
+ return labelAndSwitchCell;
+}
+
+- (void) togglePersonalNotesVisibility:(UISwitch* )sender {
+ PersonalNotesSettings* settings = [[PersonalNotesSettings alloc] init];
+ settings.personalNotesVisible = sender.on;
+}
+
#pragma mark - ThreadsBetaCoordinatorBridgePresenterDelegate
- (void)threadsBetaCoordinatorBridgePresenterDelegateDidTapEnable:(ThreadsBetaCoordinatorBridgePresenter *)coordinatorBridgePresenter
diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m
index 3cdd0bfb9..72cb22927 100644
--- a/Riot/Modules/TabBar/MasterTabBarController.m
+++ b/Riot/Modules/TabBar/MasterTabBarController.m
@@ -1079,22 +1079,6 @@
if (BWIBuildSettings.shared.bwiPersonalNotesRoom) {
[service createPersonalNotesRoomIfNeeded];
}
- if (BWIBuildSettings.shared.bwiUseCustomPersonalNotesAvatar) {
- MXSession *mainSession = mxSessionArray.firstObject;
-
- if (mainSession) {
- for (MXRoom* room in [mainSession roomsWithTag:PersonalNotesDefaultService.roomTag]) {
- if ([room.summary.avatar length] > 0) {
- [room setAvatar:@"" success:nil failure:nil];
- }
- }
-
- MXRoom* room = [mainSession roomWithRoomId:[service personalNotesRoomId]];
- if (room && [room.summary.avatar length] > 0) {
- [room setAvatar:@"" success:nil failure:nil];
- }
- }
- }
}
#pragma mark - bwi matomo tracking
@@ -1105,8 +1089,14 @@
message:[BWIL10n bwiAnalyticsAlertBody:AppInfo.current.displayName]
preferredStyle:UIAlertControllerStyleAlert];
- [alert addAction:[UIAlertAction actionWithTitle:BWIL10n.bwiAnalyticsAlertInfoButton style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
+ [alert addAction:[UIAlertAction actionWithTitle:BWIL10n.bwiAnalyticsAlertInfoButton style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
+ if (BWIBuildSettings.shared.bwiUseWellKnownPrivacyPolicyLink) {
+ if (self->mxSessionArray.firstObject.homeserverWellknown.dataPrivacyURL != nil) {
+ [[UIApplication sharedApplication] openURL:[NSURL URLWithString:self->mxSessionArray.firstObject.homeserverWellknown.dataPrivacyURL] options:@{} completionHandler:nil];
+ }
+ } else {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:BWIBuildSettings.shared.applicationPrivacyPolicyUrlString] options:@{} completionHandler:nil];
+ }
}]];
[alert addAction:[UIAlertAction actionWithTitle:BWIL10n.bwiAnalyticsAlertCancelButton style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
BWIAnalytics.sharedTracker.running = NO;
diff --git a/Riot/SupportingFiles/Riot-Bridging-Header.h b/Riot/SupportingFiles/Riot-Bridging-Header.h
index d144ac1db..66bb9bdfd 100644
--- a/Riot/SupportingFiles/Riot-Bridging-Header.h
+++ b/Riot/SupportingFiles/Riot-Bridging-Header.h
@@ -44,7 +44,7 @@
#import "ContactDetailsViewController.h"
#import "RoomInputToolbarView.h"
#import "NSArray+Element.h"
-#import "ShareItemSender.h"
+#import "ShareItemSenderProtocol.h"
#import "Contact.h"
#import "RoomTimelineCellProvider.h"
#import "PlainRoomTimelineCellProvider.h"
diff --git a/Riot/Utils/PasswordValidator.swift b/Riot/Utils/PasswordValidator.swift
index 59c6e15d4..cb70c880e 100644
--- a/Riot/Utils/PasswordValidator.swift
+++ b/Riot/Utils/PasswordValidator.swift
@@ -71,7 +71,8 @@ enum PasswordValidatorRule: CustomStringConvertible, Hashable {
case .containNumber:
return password.range(of: "[0-9]", options: .regularExpression) != nil
case .containSymbol:
- return password.range(of: "[!\"#$%&'()*+,-.:;<=>?@\\_`{|}~\\[\\]]",
+ // bwi: #4952 support more special characters
+ return password.range(of: "[!\"#$§€%&'()*+,-.:;<=>?@\\_`{|}~\\[\\]]",
options: .regularExpression) != nil
}
}
diff --git a/Riot/target.yml b/Riot/target.yml
index 791c2cb47..7ecc5fd7e 100644
--- a/Riot/target.yml
+++ b/Riot/target.yml
@@ -34,8 +34,10 @@ targets:
platform: iOS
dependencies:
- - target: RiotShareExtension
-# - target: SiriIntents
+ # Disabled due to crypto corruption issues.
+ # https://github.com/vector-im/element-ios/issues/7618
+ # - target: RiotShareExtension
+ # - target: SiriIntents // BWI: disabled
- target: RiotNSE
- target: BroadcastUploadExtension
- target: DesignKit
diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift
index eb606666e..fb92033ce 100644
--- a/RiotNSE/NotificationService.swift
+++ b/RiotNSE/NotificationService.swift
@@ -994,7 +994,9 @@ class NotificationService: UNNotificationServiceExtension {
return Constants.toBeRemovedNotificationCategoryIdentifier
}
- return "QUICK_REPLY"
+ // Don't return QUICK_REPLY here as there is an issue
+ // with crypto corruption when sending from extensions.
+ return nil
}
/// Attempts to send trigger a VoIP push for the given event
diff --git a/RiotNSE/target.yml b/RiotNSE/target.yml
index 8f65bf50d..67e644b4a 100644
--- a/RiotNSE/target.yml
+++ b/RiotNSE/target.yml
@@ -59,6 +59,7 @@ targets:
- path: ../Config/BWIBuildSettings.swift
- path: ../Config/BuM/BWIBuildSettings+BuM.swift
- path: ../bwi/UserAgent/UserAgentService.swift
+ - path: ../bwi/LoginProtection/LoginProtectionService.swift
- path: ../Riot/Utils/DataProtectionHelper.swift
- path: ../Config/CommonConfiguration.swift
- path: ../Riot/Experiments/
diff --git a/RiotSwiftUI/Modules/Authentication/Login/AuthenticationLoginModels.swift b/RiotSwiftUI/Modules/Authentication/Login/AuthenticationLoginModels.swift
index 356bd5fd3..fba209da9 100644
--- a/RiotSwiftUI/Modules/Authentication/Login/AuthenticationLoginModels.swift
+++ b/RiotSwiftUI/Modules/Authentication/Login/AuthenticationLoginModels.swift
@@ -88,11 +88,12 @@ struct AuthenticationLoginViewState: BindableState {
hasValidCredentials && !isLoading
}
- var dataPrivacyString: String {
- guard let urlString = AuthenticationService.shared.wellknown?.dataPrivacyURL() else {
+ var dataPrivacyString: String? {
+ if BWIBuildSettings.shared.bwiUseWellKnownPrivacyPolicyLink {
+ return AuthenticationService.shared.wellknown?.dataPrivacyURL()
+ } else {
return BWIBuildSettings.shared.applicationPrivacyPolicyUrlString
}
- return urlString
}
}
@@ -133,4 +134,6 @@ enum AuthenticationLoginErrorType: Hashable {
case invalidHomeserver
/// The response from the homeserver was unexpected.
case unknown
+ /// Appversion is too old
+ case appVersion
}
diff --git a/RiotSwiftUI/Modules/Authentication/Login/AuthenticationLoginViewModel.swift b/RiotSwiftUI/Modules/Authentication/Login/AuthenticationLoginViewModel.swift
index 07879621c..c3085dfa0 100644
--- a/RiotSwiftUI/Modules/Authentication/Login/AuthenticationLoginViewModel.swift
+++ b/RiotSwiftUI/Modules/Authentication/Login/AuthenticationLoginViewModel.swift
@@ -80,6 +80,16 @@ class AuthenticationLoginViewModel: AuthenticationLoginViewModelType, Authentica
message: VectorL10n.authenticationServerSelectionGenericError)
case .unknown:
state.bindings.alertInfo = AlertInfo(id: type)
+ case .appVersion:
+ state.bindings.alertInfo = AlertInfo(id: type,
+ title: BWIL10n.bwiDeprecatedVersionWarningTitle,
+ message: BWIL10n.bwiDeprecatedVersionWarningMessage,
+ primaryButton: (BWIL10n.bwiDeprecatedVersionAppstoreButton, {
+
+ UIApplication.shared.open(URL(string: BWIBuildSettings.shared.itunesAppLink)!)
+ }),
+ secondaryButton: (VectorL10n.ok, {}))
+
}
}
diff --git a/RiotSwiftUI/Modules/Authentication/Login/Coordinator/AuthenticationLoginCoordinator.swift b/RiotSwiftUI/Modules/Authentication/Login/Coordinator/AuthenticationLoginCoordinator.swift
index df7f688f4..764a42c21 100644
--- a/RiotSwiftUI/Modules/Authentication/Login/Coordinator/AuthenticationLoginCoordinator.swift
+++ b/RiotSwiftUI/Modules/Authentication/Login/Coordinator/AuthenticationLoginCoordinator.swift
@@ -130,7 +130,11 @@ final class AuthenticationLoginCoordinator: Coordinator, Presentable {
self.showForgotPasswordScreen()
}
case .login(let username, let password):
- self.login(username: username, password: password)
+ if BWIBuildSettings.shared.bwiCheckAppVersion && ValidAppVersionsDefaultService().isCurrentAppVersionDeprecated() {
+ self.authenticationLoginViewModel.displayError(.appVersion)
+ } else {
+ self.login(username: username, password: password)
+ }
case .continueWithSSO(let identityProvider):
self.callback?(.continueWithSSO(identityProvider))
case .fallback:
@@ -191,14 +195,14 @@ final class AuthenticationLoginCoordinator: Coordinator, Presentable {
@MainActor private func handleError(_ error: Error) {
if let mxError = MXError(nsError: error as NSError) {
let message = mxError.authenticationErrorMessage()
- authenticationLoginViewModel.displayError(.mxError(message))
+ self.authenticationLoginViewModel.displayError(.mxError(message))
return
}
if let authenticationError = error as? AuthenticationError {
switch authenticationError {
case .invalidHomeserver:
- authenticationLoginViewModel.displayError(.invalidHomeserver)
+ self.authenticationLoginViewModel.displayError(.invalidHomeserver)
case .loginFlowNotCalled:
#warning("Reset the flow")
case .missingMXRestClient:
@@ -207,7 +211,7 @@ final class AuthenticationLoginCoordinator: Coordinator, Presentable {
return
}
- authenticationLoginViewModel.displayError(.unknown)
+ self.authenticationLoginViewModel.displayError(.unknown)
}
@MainActor private func parseUsername(_ username: String) {
diff --git a/RiotSwiftUI/Modules/Authentication/Login/View/AuthenticationLoginScreen.swift b/RiotSwiftUI/Modules/Authentication/Login/View/AuthenticationLoginScreen.swift
index 60e1b2d35..fead5cd83 100644
--- a/RiotSwiftUI/Modules/Authentication/Login/View/AuthenticationLoginScreen.swift
+++ b/RiotSwiftUI/Modules/Authentication/Login/View/AuthenticationLoginScreen.swift
@@ -209,22 +209,31 @@ struct AuthenticationLoginScreen: View {
}
var dataPrivacyForm: some View {
- Button(action: {
- let tosURL = URL.init(string: viewModel.viewState.dataPrivacyString)! // add your link here
- if UIApplication.shared.canOpenURL(tosURL) {
- UIApplication.shared.open(tosURL)
+ VStack() {
+ if viewModel.viewState.dataPrivacyString != nil {
+ Button(action: {
+ guard let urlString = viewModel.viewState.dataPrivacyString else {
+ return
+ }
+ let tosURL = URL.init(string: urlString)! // add your link here
+ if UIApplication.shared.canOpenURL(tosURL) {
+ UIApplication.shared.open(tosURL)
+ }
+ }, label: {
+ Text(BWIL10n.authenticationDataprivacyText)
+ .font(theme.fonts.footnote)
+ .foregroundColor(theme.colors.primaryContent)
+ +
+ Text(BWIL10n.authenticationDataprivacyLink)
+ .font(theme.fonts.footnote)
+ .foregroundColor(.blue)
+ .underline()
+ })
+ .padding([.horizontal], 20)
+ } else {
+ EmptyView()
}
- }, label: {
- Text(BWIL10n.authenticationDataprivacyText)
- .font(theme.fonts.footnote)
- .foregroundColor(theme.colors.primaryContent)
- +
- Text(BWIL10n.authenticationDataprivacyLink)
- .font(theme.fonts.footnote)
- .foregroundColor(.blue)
- .underline()
- })
- .padding([.horizontal], 20)
+ }
}
var loginDescription: some View {
diff --git a/RiotSwiftUI/Modules/Authentication/ServerSelection/View/AuthenticationServerSelectionScreen.swift b/RiotSwiftUI/Modules/Authentication/ServerSelection/View/AuthenticationServerSelectionScreen.swift
index 43fc1d1eb..b42eb0eb3 100644
--- a/RiotSwiftUI/Modules/Authentication/ServerSelection/View/AuthenticationServerSelectionScreen.swift
+++ b/RiotSwiftUI/Modules/Authentication/ServerSelection/View/AuthenticationServerSelectionScreen.swift
@@ -17,10 +17,6 @@
import SwiftUI
import AVKit
-enum AuthenticationServerSelectionScreenAlertType {
- case showServerMaintenanceInfoMessageAlert, showServerMaintenanceDefaultAlert, showInvalidAppVersionAlert, showDowntimeTimeAlert, showInvalidServerAlert
-}
-
struct AuthenticationServerSelectionScreen: View {
// MARK: - Properties
@@ -39,7 +35,8 @@ struct AuthenticationServerSelectionScreen: View {
// bwi #4976 show maintenance alert
@State private var isFetchingDowntime = false
@State private var showAlert = false
- @State private var activeAlert: AuthenticationServerSelectionScreenAlertType = .showInvalidAppVersionAlert
+ @State private var isInvalidServerAlert = false
+ @State private var activeAlert: ServerMaintenanceAlertType = .showInvalidAppVersionAlert
private var textFieldFooterColor: Color {
viewModel.viewState.hasValidationError ? theme.colors.alert : theme.colors.tertiaryContent
@@ -98,67 +95,12 @@ struct AuthenticationServerSelectionScreen: View {
}
}
.alert(isPresented: $showAlert, content: {
- switch activeAlert {
- case .showInvalidAppVersionAlert:
- return Alert(title: Text(BWIL10n.bwiOutdatedVersionWarningTitle),
- message: Text(BWIL10n.bwiOutdatedVersionWarningMessage(AppInfo.current.displayName)),
- dismissButton: .destructive(Text(BWIL10n.bwiOutdatedVersionAppstoreButton), action: {
- let iTunesLink = BWIBuildSettings.shared.itunesAppLink
- UIApplication.shared.open(URL(string: iTunesLink)!, options: [:], completionHandler: nil)
- }))
- case .showDowntimeTimeAlert:
- if BWIBuildSettings.shared.ignoreBlockingMaintenance && service.isBlocking() {
- return Alert( title: Text(""),
- message: Text(ServerDowntimeDefaultService().downtimeText()),
- primaryButton: .cancel(Text(BWIL10n.blockingDowntimeAlertIgnoreButton)) {
- UserDefaults.standard.set(false, forKey: "ServerDownTimeBlockingKey")
- service.setManuallyIgnored()
- self.submit()
- },
- secondaryButton: .destructive(Text(BWIL10n.blockingDowntimeAlertDismissButton))
- )
-
- } else {
- return Alert(title: Text(BWIL10n.downtimeTitle),
- message: Text(ServerDowntimeDefaultService().downtimeText() != "" ? BWIL10n.downtimeDefaultMessage + "\n\n" + ServerDowntimeDefaultService().downtimeText() : BWIL10n.downtimeDefaultMessage),
- dismissButton: .destructive(Text(service.isBlocking() ? BWIL10n.blockingDowntimeAlertDismissButton : BWIL10n.downtimeAlertDismissButton)) {
- if service.isBlocking() {
- return
- } else {
- self.submit()
- }
- })
- }
-
- case .showServerMaintenanceInfoMessageAlert:
- if BWIBuildSettings.shared.ignoreBlockingMaintenance && service.isBlocking() {
- return Alert( title: Text(""),
- message: Text(ServerDowntimeDefaultService().downtimeText()),
- primaryButton: .cancel(Text(BWIL10n.blockingDowntimeAlertIgnoreButton)) {
- self.submit()
- },
- secondaryButton: .destructive(Text(BWIL10n.blockingDowntimeAlertDismissButton))
- )
-
- } else {
- return Alert(title: Text(""),
- message: Text(ServerDowntimeDefaultService().downtimeText()),
- dismissButton: .destructive(Text(service.isBlocking() ? BWIL10n.blockingDowntimeAlertDismissButton : BWIL10n.downtimeAlertDismissButton)) {
- if service.isBlocking() {
- return
- } else {
- self.submit()
- }
- })
- }
- case .showServerMaintenanceDefaultAlert:
- return Alert(title: Text(BWIL10n.downtimeTitle),
- message: Text(BWIL10n.downtimeDefaultMessage),
- dismissButton: .destructive(Text(BWIL10n.downtimeAlertDismissButton)) {
- self.submit()
- })
- case .showInvalidServerAlert:
+ if isInvalidServerAlert {
return self.invalidServerAlert()
+ } else {
+ return service.alert(alertType: activeAlert) {
+ self.submit()
+ }
}
})
@@ -274,7 +216,7 @@ struct AuthenticationServerSelectionScreen: View {
if isHomeserverAddressValid(viewModel.homeserverAddress) {
viewModel.send(viewAction: .confirm)
} else {
- activeAlert = .showInvalidServerAlert
+ isInvalidServerAlert = true
showAlert = true
}
}
@@ -362,18 +304,11 @@ struct AuthenticationServerSelectionScreen: View {
}
private func showAlertIfNeeded() {
- switch service.nextDowntimeStatus() {
- case .none, .warning:
- self.submit()
- break
- case .ongoing:
- if service.downtimeType() == .adhocMessage {
- activeAlert = .showServerMaintenanceInfoMessageAlert
- } else {
- activeAlert = .showDowntimeTimeAlert
- }
+ if service.showAlert() {
+ activeAlert = service.alertType()
showAlert = true
- break
+ } else {
+ self.submit()
}
}
}
diff --git a/RiotSwiftUI/Modules/Common/Avatar/Service/MatrixSDK/AvatarService.swift b/RiotSwiftUI/Modules/Common/Avatar/Service/MatrixSDK/AvatarService.swift
index ea4488244..743fec34f 100644
--- a/RiotSwiftUI/Modules/Common/Avatar/Service/MatrixSDK/AvatarService.swift
+++ b/RiotSwiftUI/Modules/Common/Avatar/Service/MatrixSDK/AvatarService.swift
@@ -29,10 +29,10 @@ class AvatarService: AvatarServiceProtocol {
static let mimeType = "image/jpeg"
static let thumbnailMethod = MXThumbnailingMethodCrop
}
+ // bwi: #5133 fix crash: make mediaManager optional
+ private let mediaManager: MXMediaManager?
- private let mediaManager: MXMediaManager
-
- init(mediaManager: MXMediaManager) {
+ init(mediaManager: MXMediaManager?) {
self.mediaManager = mediaManager
}
@@ -59,7 +59,7 @@ class AvatarService: AvatarServiceProtocol {
promise(.success(imageUp))
}
- self.mediaManager.downloadThumbnail(
+ self.mediaManager?.downloadThumbnail(
fromMatrixContentURI: mxContentUri,
withType: Constants.mimeType,
inFolder: nil,
diff --git a/RiotSwiftUI/Modules/Common/Util/ListBackground.swift b/RiotSwiftUI/Modules/Common/Util/ListBackground.swift
index d4e087da8..ddfc362c2 100644
--- a/RiotSwiftUI/Modules/Common/Util/ListBackground.swift
+++ b/RiotSwiftUI/Modules/Common/Util/ListBackground.swift
@@ -49,10 +49,4 @@ extension View {
func listBackgroundColor(_ color: Color) -> some View {
modifier(ListBackgroundModifier(color: color))
}
-
- /// Finds a `UICollectionView` from a `SwiftUI.List`, or `SwiftUI.List` child.
- /// Stop gap until https://github.com/siteline/SwiftUI-Introspect/pull/169
- func introspectCollectionView(customize: @escaping (UICollectionView) -> Void) -> some View {
- introspect(selector: TargetViewSelector.ancestorOrSiblingContaining, customize: customize)
- }
}
diff --git a/RiotSwiftUI/Modules/Room/CompletionSuggestion/Service/CompletionSuggestionService.swift b/RiotSwiftUI/Modules/Room/CompletionSuggestion/Service/CompletionSuggestionService.swift
index 5ded36c2c..c52af9506 100644
--- a/RiotSwiftUI/Modules/Room/CompletionSuggestion/Service/CompletionSuggestionService.swift
+++ b/RiotSwiftUI/Modules/Room/CompletionSuggestion/Service/CompletionSuggestionService.swift
@@ -128,7 +128,12 @@ class CompletionSuggestionService: CompletionSuggestionServiceProtocol {
items.send([])
currentTextTriggerSubject.send(nil)
case .slash:
- currentTextTriggerSubject.send(TextTrigger(key: .slash, text: suggestionPattern.text))
+ // bwi: #4955 disable WYSIWYG commands
+ if BWIBuildSettings.shared.enableWYSIWYGCommands {
+ currentTextTriggerSubject.send(TextTrigger(key: .slash, text: suggestionPattern.text))
+ } else {
+ break
+ }
}
}
diff --git a/RiotSwiftUI/Modules/Room/Composer/CreateActionList/View/ComposerCreateActionList.swift b/RiotSwiftUI/Modules/Room/Composer/CreateActionList/View/ComposerCreateActionList.swift
index 706c2f1d9..d2852cd77 100644
--- a/RiotSwiftUI/Modules/Room/Composer/CreateActionList/View/ComposerCreateActionList.swift
+++ b/RiotSwiftUI/Modules/Room/Composer/CreateActionList/View/ComposerCreateActionList.swift
@@ -39,7 +39,7 @@ struct ComposerCreateActionList: View {
HStack(spacing: 16) {
Image(action.icon)
.renderingMode(.template)
- .foregroundColor(theme.colors.accent)
+ .foregroundColor(Color(ThemeService.shared().theme.tintColor)) // bwi: #5160 color changes
Text(action.title)
.foregroundColor(theme.colors.primaryContent)
.font(theme.fonts.body)
@@ -58,7 +58,7 @@ struct ComposerCreateActionList: View {
HStack(spacing: 16) {
Image(textFormattingIcon)
.renderingMode(.template)
- .foregroundColor(theme.colors.accent)
+ .foregroundColor(Color(ThemeService.shared().theme.tintColor)) // bwi: #5160 color changes
Text(VectorL10n.wysiwygComposerStartActionTextFormatting)
.foregroundColor(theme.colors.primaryContent)
.font(theme.fonts.body)
@@ -66,7 +66,7 @@ struct ComposerCreateActionList: View {
Spacer()
Toggle("", isOn: $viewModel.textFormattingEnabled)
.labelsHidden()
- .toggleStyle(SwitchToggleStyle(tint: theme.colors.accent))
+ .toggleStyle(SwitchToggleStyle(tint: Color(ThemeService.shared().theme.tintColor))) // bwi: #5160 color changes
.onChange(of: viewModel.textFormattingEnabled) { isOn in
viewModel.send(viewAction: .toggleTextFormatting(isOn))
}
diff --git a/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordModels.swift b/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordModels.swift
index 6796dac14..5a4a27606 100644
--- a/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordModels.swift
+++ b/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordModels.swift
@@ -68,6 +68,8 @@ enum ChangePasswordViewAction {
}
enum ChangePasswordErrorType: Hashable {
+ /// The password has been changed on the server
+ case passwordChangeSucceeded
/// An error response from the homeserver.
case mxError(String)
/// User entered new passwords do not match
diff --git a/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModel.swift b/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModel.swift
index 6cfcea0e6..e9d0125c8 100644
--- a/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModel.swift
+++ b/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModel.swift
@@ -49,19 +49,25 @@ class ChangePasswordViewModel: ChangePasswordViewModelType, ChangePasswordViewMo
switch viewAction {
case .submit:
guard state.bindings.newPassword1 == state.bindings.newPassword2 else {
- Task { await displayError(.passwordsDontMatch) }
+ Task { await displayError(.passwordsDontMatch, primaryButtonCallback: {}) }
return
}
Task { await callback?(.submit(oldPassword: state.bindings.oldPassword,
newPassword: state.bindings.newPassword1,
- signoutAllDevices: state.bindings.signoutAllDevices)) }
+ signoutAllDevices: state.bindings.signoutAllDevices))
+ }
case .toggleSignoutAllDevices:
state.bindings.signoutAllDevices.toggle()
}
}
- @MainActor func displayError(_ type: ChangePasswordErrorType) {
+ @MainActor func displayError(_ type: ChangePasswordErrorType, primaryButtonCallback: @escaping (() -> Void)) {
switch type {
+ case .passwordChangeSucceeded:
+ state.bindings.alertInfo = AlertInfo(id: .passwordChangeSucceeded,
+ title: BWIL10n.settingsPasswordChanged,
+ message: "",
+ primaryButton: (VectorL10n.ok, action: { primaryButtonCallback() }))
case .mxError(let message):
state.bindings.alertInfo = AlertInfo(id: type,
title: VectorL10n.error,
diff --git a/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModelProtocol.swift b/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModelProtocol.swift
index db6848c9c..1c9ce23d9 100644
--- a/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModelProtocol.swift
+++ b/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModelProtocol.swift
@@ -21,5 +21,5 @@ protocol ChangePasswordViewModelProtocol {
var context: ChangePasswordViewModelType.Context { get }
/// Display an error to the user.
- @MainActor func displayError(_ type: ChangePasswordErrorType)
+ @MainActor func displayError(_ type: ChangePasswordErrorType, primaryButtonCallback: @escaping (() -> Void))
}
diff --git a/RiotSwiftUI/Modules/Settings/ChangePassword/Coordinator/ChangePasswordCoordinator.swift b/RiotSwiftUI/Modules/Settings/ChangePassword/Coordinator/ChangePasswordCoordinator.swift
index ef6f8a16d..522b082a3 100644
--- a/RiotSwiftUI/Modules/Settings/ChangePassword/Coordinator/ChangePasswordCoordinator.swift
+++ b/RiotSwiftUI/Modules/Settings/ChangePassword/Coordinator/ChangePasswordCoordinator.swift
@@ -110,13 +110,18 @@ final class ChangePasswordCoordinator: Coordinator, Presentable {
currentTask = Task { [weak self] in
do {
- try passwordValidator.validate(password: newPassword)
- try await parameters.restClient.changePassword(from: oldPassword, to: newPassword, logoutDevices: signoutAllDevices)
+ try self?.passwordValidator.validate(password: newPassword)
+ try await self?.parameters.restClient.changePassword(from: oldPassword, to: newPassword, logoutDevices: signoutAllDevices)
guard !Task.isCancelled else { return }
self?.stopLoading()
- self?.callback?()
+
+ if BWIBuildSettings.shared.showPasswordChangedConfirmation {
+ self?.handleSuccess()
+ } else {
+ self?.callback?()
+ }
} catch {
self?.stopLoading()
self?.handleError(error)
@@ -128,14 +133,21 @@ final class ChangePasswordCoordinator: Coordinator, Presentable {
@MainActor private func handleError(_ error: Error) {
if let mxError = MXError(nsError: error as NSError) {
let message = mxError.authenticationErrorMessage()
- changePasswordViewModel.displayError(.mxError(message))
+ changePasswordViewModel.displayError(.mxError(message), primaryButtonCallback: {})
return
}
if let error = error as? PasswordValidatorError {
- changePasswordViewModel.displayError(.mxError(error.localizedDescription))
+ changePasswordViewModel.displayError(.mxError(error.localizedDescription), primaryButtonCallback: {})
} else {
- changePasswordViewModel.displayError(.unknown)
+ changePasswordViewModel.displayError(.unknown, primaryButtonCallback: {})
}
}
+
+ // bwi: 4951 - password changed confirmation
+ @MainActor private func handleSuccess() {
+ changePasswordViewModel.displayError(.passwordChangeSucceeded, primaryButtonCallback: { [weak self] in
+ self?.callback?()
+ })
+ }
}
diff --git a/RiotSwiftUI/Modules/UserSessions/Coordinator/UserSessionsFlowCoordinator.swift b/RiotSwiftUI/Modules/UserSessions/Coordinator/UserSessionsFlowCoordinator.swift
index 17361759b..4c6de9815 100644
--- a/RiotSwiftUI/Modules/UserSessions/Coordinator/UserSessionsFlowCoordinator.swift
+++ b/RiotSwiftUI/Modules/UserSessions/Coordinator/UserSessionsFlowCoordinator.swift
@@ -120,17 +120,29 @@ final class UserSessionsFlowCoordinator: NSObject, Coordinator, Presentable {
case let .renameSession(sessionInfo):
self.showRenameSessionScreen(for: sessionInfo)
case let .logoutOfSession(sessionInfo):
- if sessionInfo.isCurrent {
- self.showLogoutConfirmationForCurrentSession()
- } else {
- self.showLogoutConfirmation(for: [sessionInfo])
- }
+ self.handleLogoutOfSession(sessionInfo: sessionInfo)
case let .showSessionStateInfo(sessionInfo):
self.showInfoSheet(parameters: .init(userSessionInfo: sessionInfo, parentSize: self.toPresentable().view.bounds.size))
}
}
pushScreen(with: coordinator)
}
+
+ private func handleLogoutOfSession(sessionInfo: UserSessionInfo) {
+ if sessionInfo.isCurrent {
+ self.showLogoutConfirmationForCurrentSession()
+ } else {
+ if let authentication = self.parameters.session.homeserverWellknown.authentication, BWIBuildSettings.shared.isOIDCEnabled {
+ if let logoutURL = authentication.getLogoutDeviceURL(fromID: sessionInfo.id) {
+ self.openDeviceLogoutRedirectURL(logoutURL)
+ } else {
+ self.showDeviceLogoutRedirectError()
+ }
+ } else {
+ self.showLogoutConfirmation(for: [sessionInfo])
+ }
+ }
+ }
/// Shows the QR login screen.
private func openQRLoginScreen() {
@@ -182,6 +194,26 @@ final class UserSessionsFlowCoordinator: NSObject, Coordinator, Presentable {
return UserOtherSessionsCoordinator(parameters: parameters)
}
+ private func openDeviceLogoutRedirectURL(_ url: URL) {
+ let alert = UIAlertController(title: VectorL10n.manageSessionRedirect, message: nil, preferredStyle: .alert)
+ alert.addAction(UIAlertAction(title: VectorL10n.ok, style: .default) { [weak self] _ in
+ UIApplication.shared.open(url) { [weak self] success in
+ guard success else {
+ return
+ }
+ self?.popToSessionsOverview()
+ }
+ })
+ alert.popoverPresentationController?.sourceView = toPresentable().view
+ navigationRouter.present(alert, animated: true)
+ }
+
+ private func showDeviceLogoutRedirectError() {
+ let alert = UIAlertController(title: VectorL10n.manageSessionRedirectError, message: nil, preferredStyle: .alert)
+ alert.popoverPresentationController?.sourceView = toPresentable().view
+ navigationRouter.present(alert, animated: true)
+ }
+
/// Shows a confirmation dialog to the user to sign out of a session.
private func showLogoutConfirmation(for sessionInfos: [UserSessionInfo]) {
// Use a UIAlertController as we don't have confirmationDialog in SwiftUI on iOS 14.
diff --git a/bwi/AppConfig/AppConfigService.swift b/bwi/AppConfig/AppConfigService.swift
index fbbbf517d..c3357464d 100644
--- a/bwi/AppConfig/AppConfigService.swift
+++ b/bwi/AppConfig/AppConfigService.swift
@@ -35,7 +35,7 @@ extension UserDefaults
@objcMembers class AppConfigService : NSObject {
static let shared = AppConfigService()
- private let serverUrlKey = "serverUrl"
+ private let serverUrlKey = "home_server_url"
private let contentScannerKey = "contentScanner"
private let pusherUrlKey = "pusherUrl"
private let permalinkUrlKey = "permalinkUrl"
@@ -50,10 +50,14 @@ extension UserDefaults
var session: MXSession?
+ var isAppConfig: Bool
+
private func loadAppConfig() {
+ isAppConfig = false
do {
if let dataIn = UserDefaults.standard.value(forKey: savedConfig) as? Data {
appConfig = try JSONDecoder().decode(AppConfig.self, from: dataIn)
+ isAppConfig = true
}
} catch {
@@ -70,17 +74,18 @@ extension UserDefaults
}
private func checkUrlSavety(_ serverUrl: String) -> Bool {
- if serverUrl.hasSuffix("bwi.de")
- || serverUrl.hasSuffix("example.com")
- || serverUrl.hasSuffix("example.com")
- || serverUrl.hasSuffix("example.com") {
- return true
+ if BWIBuildSettings.shared.bwiEnableLoginProtection {
+ let protectionService = LoginProtectionService()
+ protectionService.hashes = BWIBuildSettings.shared.bwiHashes
+
+ return protectionService.isValid(serverUrl)
} else {
- return false
+ return true
}
}
override init() {
+ isAppConfig = false
super.init()
self.loadAppConfig()
}
@@ -93,12 +98,13 @@ extension UserDefaults
}
func handleAppConfig() {
-
if let dict = UserDefaults.standard.dictionary(forKey: configKey) {
var config = AppConfig()
if let serverUrl = dict[serverUrlKey] as? String {
- if checkUrlSavety(serverUrl) {
+ if serverUrl.count == 0 {
+ config.serverUrl = nil
+ } else if checkUrlSavety(serverUrl) {
config.serverUrl = serverUrl
}
}
@@ -118,6 +124,9 @@ extension UserDefaults
}
}
+ // app config needs at least a valid server url
+ isAppConfig = (config.serverUrl != nil)
+
if config != appConfig {
appConfig = config
self.saveAppConfig()
@@ -125,6 +134,8 @@ extension UserDefaults
completion(true)
}
}
+
+ UserDefaults.standard.removeObject(forKey: configKey)
}
}
diff --git a/bwi/DeveloperSettings/DeveloperSettingsView.swift b/bwi/DeveloperSettings/DeveloperSettingsView.swift
index 7fb41e534..25a790b1e 100644
--- a/bwi/DeveloperSettings/DeveloperSettingsView.swift
+++ b/bwi/DeveloperSettings/DeveloperSettingsView.swift
@@ -94,6 +94,33 @@ struct DeveloperSettingsView: View {
}
}
}
+ SwiftUI.Section {
+ NavigationLink {
+ WellKnownView(session: session)
+ } label: {
+ Text(BWIL10n.bwiSettingsDeveloperWellKnown)
+ }
+ NavigationLink {
+ ServerCapabilitiesView(session: session)
+ } label: {
+ Text(BWIL10n.bwiSettingsDeveloperCapabilities)
+ }
+ NavigationLink {
+ MaintenanceView(session: session)
+ } label: {
+ Text(BWIL10n.bwiSettingsDeveloperMaintenance)
+ }
+ NavigationLink {
+ UserAccountDataView(session: session)
+ } label: {
+ Text(BWIL10n.bwiSettingsDeveloperUserAccountData)
+ }
+ NavigationLink {
+ ServerSideKeyBackupView(session: session)
+ } label: {
+ Text(BWIL10n.bwiSettingsDeveloperKeyBackup)
+ }
+ }
}
.listStyle(.grouped)
.navigationTitle(BWIL10n.bwiSettingsDeveloper)
diff --git a/bwi/DeveloperSettings/MaintenanceView.swift b/bwi/DeveloperSettings/MaintenanceView.swift
new file mode 100644
index 000000000..236110943
--- /dev/null
+++ b/bwi/DeveloperSettings/MaintenanceView.swift
@@ -0,0 +1,73 @@
+//
+/*
+ * Copyright (c) 2022 BWI GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 MaintenanceView: View {
+ @State var jsonString = ""
+ var session: MXSession?
+
+ var body: some View {
+ ScrollView {
+ VStack(alignment: .leading) {
+ HStack {
+ Text(jsonString)
+ .font(.caption)
+ .padding()
+ Spacer()
+ }
+ }
+ }
+ .navigationTitle(BWIL10n.bwiSettingsDeveloperMaintenance)
+ .navigationBarTitleDisplayMode(.inline)
+ .onAppear {
+ Task {
+ await fetchData()
+ }
+ }
+ }
+
+ private func fetchData() async {
+ guard let restClient = session?.matrixRestClient else {
+ return
+ }
+
+ let responseDict = await withCheckedContinuation { continuation in
+ restClient.getDowntime { jsonResponse, error in
+ continuation.resume(returning: jsonResponse)
+ }
+ }
+ await MainActor.run {
+ do {
+ if let responseDict = responseDict {
+ let data = try JSONSerialization.data(withJSONObject: responseDict as Any, options: [.prettyPrinted])
+ jsonString = String(data: data, encoding: .utf8) ?? ""
+ } else {
+ jsonString = ""
+ }
+ } catch {
+ jsonString = ""
+ }
+ }
+ }
+}
+
+struct MaintenanceView_Previews: PreviewProvider {
+ static var previews: some View {
+ MaintenanceView()
+ }
+}
diff --git a/bwi/DeveloperSettings/ServerCapabilitiesView.swift b/bwi/DeveloperSettings/ServerCapabilitiesView.swift
new file mode 100644
index 000000000..8b05f48df
--- /dev/null
+++ b/bwi/DeveloperSettings/ServerCapabilitiesView.swift
@@ -0,0 +1,73 @@
+//
+/*
+ * Copyright (c) 2022 BWI GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 ServerCapabilitiesView: View {
+ @State var jsonString = ""
+ var session: MXSession?
+
+ var body: some View {
+ ScrollView {
+ VStack(alignment: .leading) {
+ HStack {
+ Text(jsonString)
+ .font(.caption)
+ .padding()
+ Spacer()
+ }
+ }
+ }
+ .navigationTitle(BWIL10n.bwiSettingsDeveloperCapabilities)
+ .navigationBarTitleDisplayMode(.inline)
+ .onAppear {
+ Task {
+ await fetchData()
+ }
+ }
+ }
+
+ private func fetchData() async {
+ guard let restClient = session?.matrixRestClient else {
+ return
+ }
+
+ let responseDict = await withCheckedContinuation { continuation in
+ restClient.getServerCapabilities { jsonResponse, error in
+ continuation.resume(returning: jsonResponse)
+ }
+ }
+ await MainActor.run {
+ do {
+ if let responseDict = responseDict {
+ let data = try JSONSerialization.data(withJSONObject: responseDict as Any, options: [.prettyPrinted])
+ jsonString = String(data: data, encoding: .utf8) ?? ""
+ } else {
+ jsonString = ""
+ }
+ } catch {
+ jsonString = ""
+ }
+ }
+ }
+}
+
+struct ServerCapabilitiesView_Previews: PreviewProvider {
+ static var previews: some View {
+ ServerCapabilitiesView()
+ }
+}
diff --git a/bwi/DeveloperSettings/ServerSideKeyBackupView.swift b/bwi/DeveloperSettings/ServerSideKeyBackupView.swift
new file mode 100644
index 000000000..3a867b6c7
--- /dev/null
+++ b/bwi/DeveloperSettings/ServerSideKeyBackupView.swift
@@ -0,0 +1,96 @@
+//
+/*
+ * Copyright (c) 2022 BWI GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 ServerSideKeyBackupView: View {
+ @State var algorithm: String?
+ @State var count: Int?
+ @State var etag: String?
+ @State var version: String?
+ var session: MXSession?
+
+ var body: some View {
+ Form {
+ if let algorithm = algorithm {
+ TitleAndValueView(title: NSLocalizedString(BWIL10n.bwiSettingsDeveloperKeyBackupAlgorithm, comment: ""), value: algorithm)
+ }
+ if let count = count {
+ TitleAndValueView(title: NSLocalizedString(BWIL10n.bwiSettingsDeveloperKeyBackupCount, comment: ""), value: "\(count)")
+ }
+ if let etag = etag {
+ TitleAndValueView(title: NSLocalizedString(BWIL10n.bwiSettingsDeveloperKeyBackupEtag, comment: ""), value: etag)
+ }
+ if let version = version {
+ TitleAndValueView(title: NSLocalizedString(BWIL10n.bwiSettingsDeveloperKeyBackupVersion, comment: ""), value: version)
+ }
+ }
+ .navigationTitle(BWIL10n.bwiSettingsDeveloperKeyBackup)
+ .navigationBarTitleDisplayMode(.inline)
+ .onAppear {
+ Task {
+ await fetchData()
+ }
+ }
+ }
+
+ private func fetchData() async {
+ guard let restClient = session?.matrixRestClient else {
+ return
+ }
+
+ let responseDict = await withCheckedContinuation { continuation in
+ restClient.getKeyBackupVersion { jsonResponse, error in
+ continuation.resume(returning: jsonResponse)
+ }
+ }
+ await MainActor.run {
+ if let responseDict = responseDict {
+ algorithm = responseDict["algorithm"] as? String
+ count = responseDict["count"] as? Int
+ etag = responseDict["etag"] as? String
+ version = responseDict["version"] as? String
+ } else {
+ algorithm = nil
+ count = nil
+ etag = nil
+ version = nil
+ }
+ }
+ }
+
+}
+
+struct TitleAndValueView: View {
+ var title: String
+ var value: String
+
+ var body: some View {
+ HStack(alignment: .firstTextBaseline) {
+ Text(title)
+ Spacer()
+ Text(value)
+ .foregroundColor(.secondary)
+ }
+ }
+}
+
+struct ServerSideKeyBackupView_Previews: PreviewProvider {
+ static var previews: some View {
+ ServerSideKeyBackupView()
+ }
+}
diff --git a/bwi/DeveloperSettings/UserAccountDataView.swift b/bwi/DeveloperSettings/UserAccountDataView.swift
new file mode 100644
index 000000000..ec423dd99
--- /dev/null
+++ b/bwi/DeveloperSettings/UserAccountDataView.swift
@@ -0,0 +1,96 @@
+//
+/*
+ * Copyright (c) 2022 BWI GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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
+
+fileprivate let availableAccountDataTypes: [String] = [
+ "de.bwi.personal_notes_room",
+ "de.bwi.should_show_ios_release_notes",
+ "de.bwi.notification_times",
+ "de.bwi.top_banner_features",
+ "de.bwi.notifications",
+ "im.vector.setting.integration_provisioning",
+ "im.vector.setting.allowed_widgets"
+]
+
+struct UserAccountDataView: View {
+ @State var selectedAccountDataType = "de.bwi.personal_notes_room"
+ @State var jsonString = ""
+ var session: MXSession?
+
+ var body: some View {
+ Form {
+ SwiftUI.Section {
+ Picker(BWIL10n.bwiSettingsDeveloperUserAccountDataType, selection: $selectedAccountDataType) {
+ ForEach(availableAccountDataTypes, id:\.self) { type in
+ Text(type).tag(type)
+ }
+ }
+ .onChange(of: selectedAccountDataType) { newValue in
+ Task {
+ await fetchData(forType: newValue)
+ }
+ }
+ }
+ if !jsonString.isEmpty {
+ SwiftUI.Section {
+ Text(jsonString)
+ .font(.caption)
+ .padding()
+ }
+ }
+ }
+ .navigationTitle(BWIL10n.bwiSettingsDeveloperUserAccountData)
+ .navigationBarTitleDisplayMode(.inline)
+ .onAppear {
+ Task {
+ await fetchData(forType: selectedAccountDataType)
+ }
+ }
+ }
+
+ private func fetchData(forType accountDataType: String) async {
+ guard let restClient = session?.matrixRestClient else {
+ return
+ }
+
+ let responseDict = await withCheckedContinuation { continuation in
+ restClient.getAccountData(forType: accountDataType) { jsonResponse, error in
+ continuation.resume(returning: jsonResponse)
+ }
+ }
+ await MainActor.run {
+ do {
+ if let responseDict = responseDict {
+ print(responseDict)
+ let data = try JSONSerialization.data(withJSONObject: responseDict as Any, options: [.prettyPrinted])
+ jsonString = String(data: data, encoding: .utf8) ?? ""
+ } else {
+ jsonString = ""
+ }
+ } catch {
+ jsonString = ""
+ }
+ }
+ }
+}
+
+struct UserAccountDataView_Previews: PreviewProvider {
+ static var previews: some View {
+ UserAccountDataView()
+ }
+}
diff --git a/bwi/DeveloperSettings/WellKnownView.swift b/bwi/DeveloperSettings/WellKnownView.swift
new file mode 100644
index 000000000..df63e02eb
--- /dev/null
+++ b/bwi/DeveloperSettings/WellKnownView.swift
@@ -0,0 +1,73 @@
+//
+/*
+ * Copyright (c) 2022 BWI GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 WellKnownView: View {
+ @State var jsonString = ""
+ var session: MXSession?
+
+ var body: some View {
+ ScrollView {
+ VStack(alignment: .leading) {
+ HStack {
+ Text(jsonString)
+ .font(.caption)
+ .padding()
+ Spacer()
+ }
+ }
+ }
+ .navigationTitle(BWIL10n.bwiSettingsDeveloperWellKnown)
+ .navigationBarTitleDisplayMode(.inline)
+ .onAppear {
+ Task {
+ await fetchData()
+ }
+ }
+ }
+
+ private func fetchData() async {
+ guard let restClient = session?.matrixRestClient else {
+ return
+ }
+
+ let responseDict = await withCheckedContinuation { continuation in
+ restClient.getWellKnown { jsonResponse, error in
+ continuation.resume(returning: jsonResponse)
+ }
+ }
+ await MainActor.run {
+ do {
+ if let responseDict = responseDict {
+ let data = try JSONSerialization.data(withJSONObject: responseDict as Any, options: [.prettyPrinted])
+ jsonString = String(data: data, encoding: .utf8) ?? ""
+ } else {
+ jsonString = ""
+ }
+ } catch {
+ jsonString = ""
+ }
+ }
+ }
+}
+
+struct WellKnownView_Previews: PreviewProvider {
+ static var previews: some View {
+ WellKnownView()
+ }
+}
diff --git a/bwi/PersonalNotes/PersonalNotesDefaultService.swift b/bwi/PersonalNotes/PersonalNotesDefaultService.swift
index b6f9023b4..67a222e11 100644
--- a/bwi/PersonalNotes/PersonalNotesDefaultService.swift
+++ b/bwi/PersonalNotes/PersonalNotesDefaultService.swift
@@ -90,7 +90,7 @@ import MatrixSDK
}
extension PersonalNotesDefaultService : PersonalNotesService {
-
+
func personalNotesRoomId() -> String? {
guard let personalNotesRoom = self.personalNotesRoom() else {
return nil
@@ -119,12 +119,12 @@ extension PersonalNotesDefaultService : PersonalNotesService {
case .success(let room):
_ = self.setRoomId(roomId: room.roomId)
- let tagOrder = self.session.tagOrderToBe(at: 0, from: UInt(NSNotFound), withTag: PersonalNotesDefaultService.roomTag) ?? ""
- room.replaceTag(PersonalNotesDefaultService.roomTag, with: PersonalNotesDefaultService.roomTag, withOrder: tagOrder) { (response) in
+ let tagOrder = self.session.tagOrderToBe(at: 0, from: UInt(NSNotFound), withTag: kMXRoomTagFavourite) ?? ""
+ room.replaceTag(kMXRoomTagFavourite, with: kMXRoomTagFavourite, withOrder: tagOrder) { (response) in
}
- case .failure(let error):
- MXLog.error("**BWI** Personal Notes creation failure:")
+ case .failure(_ ):
+ MXLog.error("**BWI** Personal Notes creation failure")
}
}
}
@@ -138,4 +138,17 @@ extension PersonalNotesDefaultService : PersonalNotesService {
func avatarImageUrl() -> String {
return self.defaultAvatar
}
+
+ func setAsFavoriteIfNeeded() {
+ if let room = self.session.room(withRoomId: self.personalNotesRoomId()) {
+ if room.accountData.tags[kMXRoomTagFavourite] == nil {
+ let tagOrder = self.session.tagOrderToBe(at: 0, from: UInt(NSNotFound), withTag: kMXRoomTagFavourite) ?? ""
+ room.replaceTag(kMXRoomTagFavourite, with: kMXRoomTagFavourite, withOrder: tagOrder) { (response) in
+ // check old settings
+ let layoutSettings = AllChatsLayoutSettingsManager.shared.allChatLayoutSettings
+ PersonalNotesSettings().personalNotesVisible = layoutSettings.sections.contains(.bwiPersonalNotes)
+ }
+ }
+ }
+ }
}
diff --git a/bwi/PersonalNotes/PersonalNotesService.swift b/bwi/PersonalNotes/PersonalNotesService.swift
index 64a92d80f..5b33efca5 100644
--- a/bwi/PersonalNotes/PersonalNotesService.swift
+++ b/bwi/PersonalNotes/PersonalNotesService.swift
@@ -24,4 +24,6 @@ protocol PersonalNotesService {
func resetPersonalNotesRoom()
func avatarImageUrl() -> String
+
+ func setAsFavoriteIfNeeded()
}
diff --git a/bwi/PollParticipantDetails/PollParticipantDetailsModels.swift b/bwi/PollParticipantDetails/PollParticipantDetailsModels.swift
index 2a8f11599..192b0363d 100644
--- a/bwi/PollParticipantDetails/PollParticipantDetailsModels.swift
+++ b/bwi/PollParticipantDetails/PollParticipantDetailsModels.swift
@@ -49,8 +49,15 @@ struct PollParticipantVoter: Identifiable, BindableState {
let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone.current
dateFormatter.calendar = Calendar.current
- dateFormatter.dateFormat = "dd. MMMM, yyyy HH:mm"
- let strDate = dateFormatter.string(from: votingTime)
+ var strDate = ""
+ if Calendar.current.isDateInToday(votingTime) {
+ dateFormatter.dateFormat = "HH:mm"
+ strDate = BWIL10n.pollParticipantDetailsDateStringToday.appending(dateFormatter.string(from: votingTime))
+ } else {
+ dateFormatter.dateFormat = "E, d. MMM yyyy, HH:mm"
+ strDate = dateFormatter.string(from: votingTime)
+ }
+ strDate.append(contentsOf: BWIL10n.pollParticipantDetailsClockString)
return PollParticipantVoter(displayName: user.displayname, userAvatarData: avatarData, formattedVotingTime: strDate)
} else {
diff --git a/bwi/PollParticipantDetails/PollParticipantDetailsView.swift b/bwi/PollParticipantDetails/PollParticipantDetailsView.swift
index 7b9bb6c4a..0990f411a 100644
--- a/bwi/PollParticipantDetails/PollParticipantDetailsView.swift
+++ b/bwi/PollParticipantDetails/PollParticipantDetailsView.swift
@@ -86,6 +86,7 @@ struct PollParticipantVoterView: View {
.font(theme.fonts.footnote)
.foregroundColor(theme.colors.secondaryContent)
}
+ Spacer()
}
}
}
diff --git a/bwi/ServerMaintenance/ServerDownTimeBadge.swift b/bwi/ServerMaintenance/ServerDownTimeBadge.swift
index 90e72efcf..ec2a94303 100644
--- a/bwi/ServerMaintenance/ServerDownTimeBadge.swift
+++ b/bwi/ServerMaintenance/ServerDownTimeBadge.swift
@@ -21,7 +21,7 @@ import UIKit
@objcMembers class ServerDowntimeBadge : NSObject {
func applyBadgeToButton(button: UIButton, color: UIColor) -> UIButton {
- let badge = UILabel.init(frame: CGRect.init(x: 15, y: 0, width: 15, height: 15))
+ let badge = UILabel.init(frame: CGRect.init(x: 20, y: 0, width: 15, height: 15))
badge.backgroundColor = color
badge.clipsToBounds = true
badge.layer.cornerRadius = 7
diff --git a/bwi/ServerMaintenance/ServerDownTimeService.swift b/bwi/ServerMaintenance/ServerDownTimeService.swift
index 904bd0468..5ae327438 100644
--- a/bwi/ServerMaintenance/ServerDownTimeService.swift
+++ b/bwi/ServerMaintenance/ServerDownTimeService.swift
@@ -16,6 +16,7 @@
*/
import Foundation
+import SwiftUI
enum ServerDowntimeStatus {
case none
@@ -23,6 +24,10 @@ enum ServerDowntimeStatus {
case ongoing
}
+enum ServerMaintenanceAlertType {
+ case showServerMaintenanceInfoMessageAlert, showServerMaintenanceDefaultAlert, showInvalidAppVersionAlert, showDowntimeTimeAlert
+}
+
enum ServerDowntimeType: String {
case adhocMessage = "ADHOC_MESSAGE"
case maintenance = "MAINTENANCE"
@@ -38,4 +43,7 @@ protocol ServerDowntimeService {
func isBlocking() -> Bool
func setManuallyIgnored()
func isManuallyIgnored() -> Bool
+ func alert( alertType:ServerMaintenanceAlertType, completion: @escaping () -> Void) -> Alert
+ func showAlert() -> Bool
+ func alertType() -> ServerMaintenanceAlertType
}
diff --git a/bwi/ServerMaintenance/ServerDowntimeDefaultService.swift b/bwi/ServerMaintenance/ServerDowntimeDefaultService.swift
index 11bba57aa..919e0071b 100644
--- a/bwi/ServerMaintenance/ServerDowntimeDefaultService.swift
+++ b/bwi/ServerMaintenance/ServerDowntimeDefaultService.swift
@@ -18,6 +18,7 @@
import Foundation
import UIKit
import MatrixSDK
+import SwiftUI
fileprivate let BWI_ServerDowntimes = "BWI_ServerDowntimes"
@@ -150,6 +151,80 @@ fileprivate let maintenanceURL = "/_matrix/cmaintenance"
extension ServerDowntimeDefaultService : ServerDowntimeService {
+ func alert(alertType: ServerMaintenanceAlertType, completion: @escaping () -> Void) -> Alert {
+ switch alertType {
+ case .showInvalidAppVersionAlert:
+ return Alert(title: Text(BWIL10n.bwiOutdatedVersionWarningTitle),
+ message: Text(BWIL10n.bwiOutdatedVersionWarningMessage(AppInfo.current.displayName)),
+ dismissButton: .destructive(Text(BWIL10n.bwiOutdatedVersionAppstoreButton), action: {
+ let iTunesLink = BWIBuildSettings.shared.itunesAppLink
+ UIApplication.shared.open(URL(string: iTunesLink)!, options: [:], completionHandler: nil)
+ }))
+ case .showDowntimeTimeAlert:
+ if BWIBuildSettings.shared.ignoreBlockingMaintenance && isBlocking() {
+ return Alert( title: Text(""),
+ message: Text(ServerDowntimeDefaultService().downtimeText()),
+ primaryButton: .cancel(Text(BWIL10n.blockingDowntimeAlertIgnoreButton)) {
+ UserDefaults.standard.set(false, forKey: "ServerDownTimeBlockingKey")
+ self.setManuallyIgnored()
+ completion()
+ },
+ secondaryButton: .destructive(Text(BWIL10n.blockingDowntimeAlertDismissButton))
+ )
+
+ } else {
+ return Alert(title: Text(BWIL10n.downtimeTitle),
+ message: Text(ServerDowntimeDefaultService().downtimeText() != "" ? BWIL10n.downtimeDefaultMessage + "\n\n" + ServerDowntimeDefaultService().downtimeText() : BWIL10n.downtimeDefaultMessage),
+ dismissButton: .destructive(Text(isBlocking() ? BWIL10n.blockingDowntimeAlertDismissButton : BWIL10n.downtimeAlertDismissButton)) {
+ if self.isBlocking() {
+ return
+ } else {
+ completion()
+ }
+ })
+ }
+ case .showServerMaintenanceInfoMessageAlert:
+ if BWIBuildSettings.shared.ignoreBlockingMaintenance && isBlocking() {
+ return Alert( title: Text(""),
+ message: Text(ServerDowntimeDefaultService().downtimeText()),
+ primaryButton: .cancel(Text(BWIL10n.blockingDowntimeAlertIgnoreButton)) {
+ completion()
+ },
+ secondaryButton: .destructive(Text(BWIL10n.blockingDowntimeAlertDismissButton))
+ )
+
+ } else {
+ return Alert(title: Text(""),
+ message: Text(ServerDowntimeDefaultService().downtimeText()),
+ dismissButton: .destructive(Text(isBlocking() ? BWIL10n.blockingDowntimeAlertDismissButton : BWIL10n.downtimeAlertDismissButton)) {
+ if self.isBlocking() {
+ return
+ } else {
+ completion()
+ }
+ })
+ }
+ case .showServerMaintenanceDefaultAlert:
+ return Alert(title: Text(BWIL10n.downtimeTitle),
+ message: Text(BWIL10n.downtimeDefaultMessage),
+ dismissButton: .destructive(Text(BWIL10n.downtimeAlertDismissButton)) {
+ completion()
+ })
+ }
+ }
+
+ func showAlert() -> Bool {
+ return nextDowntimeStatus() == .ongoing
+ }
+
+ func alertType() -> ServerMaintenanceAlertType {
+ if downtimeType() == .adhocMessage {
+ return .showServerMaintenanceInfoMessageAlert
+ } else {
+ return .showDowntimeTimeAlert
+ }
+ }
+
func fetchDowntimes(session: MXSession, completion: @escaping () -> Void) {
session.matrixRestClient.getDowntime(completion: { (jsonResponse, error) in
do {
diff --git a/bwi/SplashScreen/View/OnboardingBwiSplashScreen.swift b/bwi/SplashScreen/View/OnboardingBwiSplashScreen.swift
index ad508412a..d9aa25ce4 100644
--- a/bwi/SplashScreen/View/OnboardingBwiSplashScreen.swift
+++ b/bwi/SplashScreen/View/OnboardingBwiSplashScreen.swift
@@ -16,10 +16,6 @@
import SwiftUI
-enum OnBoardingSplashScreenAlertType {
- case showServerMaintenanceInfoMessageAlert, showServerMaintenanceDefaultAlert, showInvalidAppVersionAlert, showDowntimeTimeAlert
-}
-
@available(iOS 14.0, *)
/// The splash screen shown at the beginning of the onboarding flow.
struct OnboardingBwiSplashScreen: View {
@@ -36,7 +32,7 @@ struct OnboardingBwiSplashScreen: View {
@State private var overlayFrame: CGRect = .zero
@State private var isFetchingDowntime = false
@State private var showAlert = false
- @State private var activeAlert: OnBoardingSplashScreenAlertType = .showInvalidAppVersionAlert
+ @State private var activeAlert: ServerMaintenanceAlertType = .showInvalidAppVersionAlert
// MARK: Public
@@ -79,40 +75,8 @@ struct OnboardingBwiSplashScreen: View {
.navigationTitle("")
.navigationBarHidden(true)
.alert(isPresented: $showAlert, content: {
- switch activeAlert {
- case .showInvalidAppVersionAlert:
- return Alert(title: Text(BWIL10n.bwiOutdatedVersionWarningTitle),
- message: Text(BWIL10n.bwiOutdatedVersionWarningMessage(AppInfo.current.displayName)),
- dismissButton: .destructive(Text(BWIL10n.bwiOutdatedVersionAppstoreButton), action: {
- let iTunesLink = BWIBuildSettings.shared.itunesAppLink
- UIApplication.shared.open(URL(string: iTunesLink)!, options: [:], completionHandler: nil)
- }))
- case .showDowntimeTimeAlert:
- return Alert(title: Text(BWIL10n.downtimeTitle),
- message: Text(ServerDowntimeDefaultService().downtimeText() != "" ? BWIL10n.downtimeDefaultMessage + "\n\n" + ServerDowntimeDefaultService().downtimeText() : BWIL10n.downtimeDefaultMessage),
- dismissButton: .destructive(Text(service.isBlocking() ? BWIL10n.blockingDowntimeAlertDismissButton : BWIL10n.downtimeAlertDismissButton)) {
- if service.isBlocking() {
- return
- } else {
- viewModel.send(viewAction: .login)
- }
- })
- case .showServerMaintenanceInfoMessageAlert:
- return Alert(title: Text(""),
- message: Text(ServerDowntimeDefaultService().downtimeText()),
- dismissButton: .destructive(Text(service.isBlocking() ? BWIL10n.blockingDowntimeAlertDismissButton : BWIL10n.downtimeAlertDismissButton)) {
- if service.isBlocking() {
- return
- } else {
- viewModel.send(viewAction: .login)
- }
- })
- case .showServerMaintenanceDefaultAlert:
- return Alert(title: Text(BWIL10n.downtimeTitle),
- message: Text(BWIL10n.downtimeDefaultMessage),
- dismissButton: .destructive(Text(BWIL10n.downtimeAlertDismissButton)) {
- viewModel.send(viewAction: .login)
- })
+ service.alert(alertType: activeAlert) {
+ viewModel.send(viewAction: .login)
}
})
}
@@ -146,24 +110,11 @@ struct OnboardingBwiSplashScreen: View {
private func showAlertIfNeeded() {
- switch service.nextDowntimeStatus() {
- case .none:
- viewModel.send(viewAction: .login)
- break
- case .ongoing:
- if service.downtimeType() == .adhocMessage {
- activeAlert = .showServerMaintenanceInfoMessageAlert
- } else {
- activeAlert = .showDowntimeTimeAlert
- }
+ if service.showAlert() {
+ activeAlert = service.alertType()
showAlert = true
- break
- case .warning:
- // only show active downtimes
+ } else {
viewModel.send(viewAction: .login)
- // showAlert = true
- // activeAlert = .showServerMaintenanceAlert
- break
}
}
}
diff --git a/bwi/Tools/BWIRestClient.swift b/bwi/Tools/BWIRestClient.swift
index ff71310dc..21b49bae4 100644
--- a/bwi/Tools/BWIRestClient.swift
+++ b/bwi/Tools/BWIRestClient.swift
@@ -17,7 +17,49 @@
import Foundation
public extension MXRestClient {
+
+ @discardableResult
+ func getWellKnown(completion: @escaping (_ jsonResponse: Dictionary