Merge branch 'release/v2.10.0'

This commit is contained in:
JanNiklas Grabowski
2023-10-04 15:50:19 +02:00
115 changed files with 2122 additions and 650 deletions
+36
View File
@@ -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
+34
View File
@@ -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)
===================================================
+4
View File
@@ -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
}
+1 -1
View File
@@ -16,5 +16,5 @@
//
// Version
MARKETING_VERSION = 2.9.1
MARKETING_VERSION = 2.10.0
CURRENT_PROJECT_VERSION = 20220714163152
+27 -4
View File
@@ -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
}
@@ -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
}
}
@@ -31,6 +31,7 @@ extension BWIBuildSettings {
bwiEnableLoginProtection = false
itunesAppLink = "itms://itunes.apple.com/app/bundesmessenger-open/id6450672686?mt=8"
avoidServerSelectionOnAppConfig = true
}
}
+2
View File
@@ -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
}
}
+1 -1
View File
@@ -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
+16 -2
View File
@@ -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
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 $?
+16 -4
View File
@@ -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|
+62 -21
View File
@@ -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
@@ -0,0 +1,17 @@
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_790_1087)">
<circle cx="32" cy="28" r="28" fill="white"/>
</g>
<path d="M23.9447 38.5279C23.3789 38.5279 22.9 38.3319 22.508 37.9399C22.116 37.5479 21.92 37.069 21.92 36.5033V21.5126C21.92 20.9468 22.116 20.468 22.508 20.076C22.9 19.684 23.3789 19.488 23.9447 19.488H33.5099L31.8299 21.1679H23.9447C23.8585 21.1679 23.7795 21.2038 23.7077 21.2756C23.6359 21.3474 23.6 21.4264 23.6 21.5126V36.5033C23.6 36.5895 23.6359 36.6684 23.7077 36.7403C23.7795 36.812 23.8585 36.8479 23.9447 36.8479H38.9354C39.0215 36.8479 39.1005 36.812 39.1723 36.7403C39.2441 36.6684 39.28 36.5895 39.28 36.5033V28.6008L40.96 26.9209V36.5033C40.96 37.069 40.764 37.5479 40.372 37.9399C39.98 38.3319 39.5011 38.5279 38.9354 38.5279H23.9447ZM36.5145 19.9597L37.7228 21.1399L30.32 28.5319V30.1279H31.888L39.3295 22.7079L40.5163 23.8774L32.6138 31.8079H28.64V27.8341L36.5145 19.9597ZM40.5163 23.8774L36.5145 19.9597L39.0776 17.3966C39.4753 16.9989 39.9581 16.8 40.526 16.8C41.0939 16.8 41.571 17.0025 41.9572 17.4074L43.0514 18.5079C43.4376 18.9014 43.6307 19.3756 43.6307 19.9306C43.6307 20.4855 43.434 20.9597 43.0406 21.3532L40.5163 23.8774Z" fill="#108194"/>
<defs>
<filter id="filter0_d_790_1087" x="0" y="0" width="64" height="64" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_790_1087"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_790_1087" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "Button_BuM_Dark.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,17 @@
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_790_1079)">
<circle cx="32" cy="28" r="28" fill="#108194"/>
</g>
<path d="M23.9447 38.5279C23.3789 38.5279 22.9 38.3319 22.508 37.9399C22.116 37.5479 21.92 37.069 21.92 36.5033V21.5126C21.92 20.9468 22.116 20.468 22.508 20.076C22.9 19.684 23.3789 19.488 23.9447 19.488H33.5099L31.8299 21.1679H23.9447C23.8585 21.1679 23.7795 21.2038 23.7077 21.2756C23.6359 21.3474 23.6 21.4264 23.6 21.5126V36.5033C23.6 36.5895 23.6359 36.6684 23.7077 36.7403C23.7795 36.812 23.8585 36.8479 23.9447 36.8479H38.9354C39.0215 36.8479 39.1005 36.812 39.1723 36.7403C39.2441 36.6684 39.28 36.5895 39.28 36.5033V28.6008L40.96 26.9209V36.5033C40.96 37.069 40.764 37.5479 40.372 37.9399C39.98 38.3319 39.5011 38.5279 38.9354 38.5279H23.9447ZM36.5145 19.9597L37.7228 21.1399L30.32 28.5319V30.1279H31.888L39.3295 22.7079L40.5163 23.8774L32.6138 31.8079H28.64V27.8341L36.5145 19.9597ZM40.5163 23.8774L36.5145 19.9597L39.0776 17.3966C39.4753 16.9989 39.9581 16.8 40.526 16.8C41.0939 16.8 41.571 17.0025 41.9572 17.4074L43.0514 18.5079C43.4376 18.9014 43.6307 19.3756 43.6307 19.9306C43.6307 20.4855 43.434 20.9597 43.0406 21.3532L40.5163 23.8774Z" fill="white"/>
<defs>
<filter id="filter0_d_790_1079" x="0" y="0" width="64" height="64" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_790_1079"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_790_1079" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "Button_BuM_Light.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "settings-filled.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}
@@ -0,0 +1,8 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0_674_1214" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="24" height="24">
<rect width="24" height="24" fill="#D9D9D9"/>
</mask>
<g mask="url(#mask0_674_1214)">
<path d="M13.875 22H10.125C9.87497 22 9.6583 21.9167 9.47497 21.75C9.29164 21.5833 9.1833 21.375 9.14997 21.125L8.84997 18.8C8.6333 18.7167 8.42914 18.6167 8.23747 18.5C8.0458 18.3833 7.8583 18.2583 7.67497 18.125L5.49997 19.025C5.26664 19.1083 5.0333 19.1167 4.79997 19.05C4.56664 18.9833 4.3833 18.8417 4.24997 18.625L2.39997 15.4C2.26664 15.1833 2.22497 14.95 2.27497 14.7C2.32497 14.45 2.44997 14.25 2.64997 14.1L4.52497 12.675C4.5083 12.5583 4.49997 12.4458 4.49997 12.3375V11.6625C4.49997 11.5542 4.5083 11.4417 4.52497 11.325L2.64997 9.9C2.44997 9.75 2.32497 9.55 2.27497 9.3C2.22497 9.05 2.26664 8.81667 2.39997 8.6L4.24997 5.375C4.36664 5.14167 4.5458 4.99583 4.78747 4.9375C5.02914 4.87917 5.26664 4.89167 5.49997 4.975L7.67497 5.875C7.8583 5.74167 8.04997 5.61667 8.24997 5.5C8.44997 5.38333 8.64997 5.28333 8.84997 5.2L9.14997 2.875C9.1833 2.625 9.29164 2.41667 9.47497 2.25C9.6583 2.08333 9.87497 2 10.125 2H13.875C14.125 2 14.3416 2.08333 14.525 2.25C14.7083 2.41667 14.8166 2.625 14.85 2.875L15.15 5.2C15.3666 5.28333 15.5708 5.38333 15.7625 5.5C15.9541 5.61667 16.1416 5.74167 16.325 5.875L18.5 4.975C18.7333 4.89167 18.9666 4.88333 19.2 4.95C19.4333 5.01667 19.6166 5.15833 19.75 5.375L21.6 8.6C21.7333 8.81667 21.775 9.05 21.725 9.3C21.675 9.55 21.55 9.75 21.35 9.9L19.475 11.325C19.4916 11.4417 19.5 11.5542 19.5 11.6625V12.3375C19.5 12.4458 19.4833 12.5583 19.45 12.675L21.325 14.1C21.525 14.25 21.65 14.45 21.7 14.7C21.75 14.95 21.7083 15.1833 21.575 15.4L19.725 18.6C19.5916 18.8167 19.4041 18.9625 19.1625 19.0375C18.9208 19.1125 18.6833 19.1083 18.45 19.025L16.325 18.125C16.1416 18.2583 15.95 18.3833 15.75 18.5C15.55 18.6167 15.35 18.7167 15.15 18.8L14.85 21.125C14.8166 21.375 14.7083 21.5833 14.525 21.75C14.3416 21.9167 14.125 22 13.875 22ZM12.05 15.5C13.0166 15.5 13.8416 15.1583 14.525 14.475C15.2083 13.7917 15.55 12.9667 15.55 12C15.55 11.0333 15.2083 10.2083 14.525 9.525C13.8416 8.84167 13.0166 8.5 12.05 8.5C11.0666 8.5 10.2375 8.84167 9.56247 9.525C8.88747 10.2083 8.54997 11.0333 8.54997 12C8.54997 12.9667 8.88747 13.7917 9.56247 14.475C10.2375 15.1583 11.0666 15.5 12.05 15.5Z" fill="#13293D"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "Filter-dark.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11 19C10.7167 19 10.4792 18.9042 10.2875 18.7125C10.0958 18.5208 10 18.2833 10 18C10 17.7167 10.0958 17.4792 10.2875 17.2875C10.4792 17.0958 10.7167 17 11 17H13C13.2833 17 13.5208 17.0958 13.7125 17.2875C13.9042 17.4792 14 17.7167 14 18C14 18.2833 13.9042 18.5208 13.7125 18.7125C13.5208 18.9042 13.2833 19 13 19H11ZM4 9C3.71667 9 3.47917 8.90417 3.2875 8.7125C3.09583 8.52083 3 8.28333 3 8C3 7.71667 3.09583 7.47917 3.2875 7.2875C3.47917 7.09583 3.71667 7 4 7H20C20.2833 7 20.5208 7.09583 20.7125 7.2875C20.9042 7.47917 21 7.71667 21 8C21 8.28333 20.9042 8.52083 20.7125 8.7125C20.5208 8.90417 20.2833 9 20 9H4ZM7 14C6.71667 14 6.47917 13.9042 6.2875 13.7125C6.09583 13.5208 6 13.2833 6 13C6 12.7167 6.09583 12.4792 6.2875 12.2875C6.47917 12.0958 6.71667 12 7 12H17C17.2833 12 17.5208 12.0958 17.7125 12.2875C17.9042 12.4792 18 12.7167 18 13C18 13.2833 17.9042 13.5208 17.7125 13.7125C17.5208 13.9042 17.2833 14 17 14H7Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "Filter-pressed-dark.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,11 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_101_2907)">
<circle cx="12" cy="12" r="12" fill="#425464"/>
<path d="M11.1111 18.6667C10.8593 18.6667 10.6481 18.5815 10.4778 18.4111C10.3074 18.2407 10.2222 18.0296 10.2222 17.7778C10.2222 17.5259 10.3074 17.3148 10.4778 17.1444C10.6481 16.9741 10.8593 16.8889 11.1111 16.8889H12.8889C13.1407 16.8889 13.3519 16.9741 13.5222 17.1444C13.6926 17.3148 13.7778 17.5259 13.7778 17.7778C13.7778 18.0296 13.6926 18.2407 13.5222 18.4111C13.3519 18.5815 13.1407 18.6667 12.8889 18.6667H11.1111ZM4.88889 9.77778C4.63704 9.77778 4.42593 9.69259 4.25556 9.52222C4.08519 9.35185 4 9.14074 4 8.88889C4 8.63704 4.08519 8.42593 4.25556 8.25556C4.42593 8.08519 4.63704 8 4.88889 8H19.1111C19.363 8 19.5741 8.08519 19.7444 8.25556C19.9148 8.42593 20 8.63704 20 8.88889C20 9.14074 19.9148 9.35185 19.7444 9.52222C19.5741 9.69259 19.363 9.77778 19.1111 9.77778H4.88889ZM7.55556 14.2222C7.3037 14.2222 7.09259 14.137 6.92222 13.9667C6.75185 13.7963 6.66667 13.5852 6.66667 13.3333C6.66667 13.0815 6.75185 12.8704 6.92222 12.7C7.09259 12.5296 7.3037 12.4444 7.55556 12.4444H16.4444C16.6963 12.4444 16.9074 12.5296 17.0778 12.7C17.2481 12.8704 17.3333 13.0815 17.3333 13.3333C17.3333 13.5852 17.2481 13.7963 17.0778 13.9667C16.9074 14.137 16.6963 14.2222 16.4444 14.2222H7.55556Z" fill="white"/>
</g>
<defs>
<clipPath id="clip0_101_2907">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "Filter-light.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11 19C10.7167 19 10.4792 18.9042 10.2875 18.7125C10.0958 18.5208 10 18.2833 10 18C10 17.7167 10.0958 17.4792 10.2875 17.2875C10.4792 17.0958 10.7167 17 11 17H13C13.2833 17 13.5208 17.0958 13.7125 17.2875C13.9042 17.4792 14 17.7167 14 18C14 18.2833 13.9042 18.5208 13.7125 18.7125C13.5208 18.9042 13.2833 19 13 19H11ZM4 9C3.71667 9 3.47917 8.90417 3.2875 8.7125C3.09583 8.52083 3 8.28333 3 8C3 7.71667 3.09583 7.47917 3.2875 7.2875C3.47917 7.09583 3.71667 7 4 7H20C20.2833 7 20.5208 7.09583 20.7125 7.2875C20.9042 7.47917 21 7.71667 21 8C21 8.28333 20.9042 8.52083 20.7125 8.7125C20.5208 8.90417 20.2833 9 20 9H4ZM7 14C6.71667 14 6.47917 13.9042 6.2875 13.7125C6.09583 13.5208 6 13.2833 6 13C6 12.7167 6.09583 12.4792 6.2875 12.2875C6.47917 12.0958 6.71667 12 7 12H17C17.2833 12 17.5208 12.0958 17.7125 12.2875C17.9042 12.4792 18 12.7167 18 13C18 13.2833 17.9042 13.5208 17.7125 13.7125C17.5208 13.9042 17.2833 14 17 14H7Z" fill="#13293D"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "Filter-pressed-light.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,11 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_141_5661)">
<circle cx="12" cy="12" r="12" fill="#E3E8F0"/>
<path d="M11.1111 18.6667C10.8593 18.6667 10.6481 18.5815 10.4778 18.4111C10.3074 18.2407 10.2222 18.0296 10.2222 17.7778C10.2222 17.5259 10.3074 17.3148 10.4778 17.1444C10.6481 16.9741 10.8593 16.8889 11.1111 16.8889H12.8889C13.1407 16.8889 13.3519 16.9741 13.5222 17.1444C13.6926 17.3148 13.7778 17.5259 13.7778 17.7778C13.7778 18.0296 13.6926 18.2407 13.5222 18.4111C13.3519 18.5815 13.1407 18.6667 12.8889 18.6667H11.1111ZM4.88889 9.77778C4.63704 9.77778 4.42593 9.69259 4.25556 9.52222C4.08519 9.35185 4 9.14074 4 8.88889C4 8.63704 4.08519 8.42593 4.25556 8.25556C4.42593 8.08519 4.63704 8 4.88889 8H19.1111C19.363 8 19.5741 8.08519 19.7444 8.25556C19.9148 8.42593 20 8.63704 20 8.88889C20 9.14074 19.9148 9.35185 19.7444 9.52222C19.5741 9.69259 19.363 9.77778 19.1111 9.77778H4.88889ZM7.55556 14.2222C7.3037 14.2222 7.09259 14.137 6.92222 13.9667C6.75185 13.7963 6.66667 13.5852 6.66667 13.3333C6.66667 13.0815 6.75185 12.8704 6.92222 12.7C7.09259 12.5296 7.3037 12.4444 7.55556 12.4444H16.4444C16.6963 12.4444 16.9074 12.5296 17.0778 12.7C17.2481 12.8704 17.3333 13.0815 17.3333 13.3333C17.3333 13.5852 17.2481 13.7963 17.0778 13.9667C16.9074 14.137 16.6963 14.2222 16.4444 14.2222H7.55556Z" fill="#13293D"/>
</g>
<defs>
<clipPath id="clip0_141_5661">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 KiB

@@ -9,7 +9,7 @@
"scale" : "2x"
},
{
"filename" : "BWI-noticeboard.png",
"filename" : "Notizen-Avatar.svg",
"idiom" : "universal",
"scale" : "3x"
}
@@ -0,0 +1,4 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="16" cy="16" r="16" fill="#DEBB6B"/>
<path d="M13.5 20.7913H18.5C18.6771 20.7913 18.8255 20.7314 18.9453 20.6116C19.0651 20.4917 19.125 20.3432 19.125 20.166C19.125 19.9889 19.0651 19.8405 18.9453 19.7208C18.8255 19.6012 18.6771 19.5413 18.5 19.5413H13.5C13.3229 19.5413 13.1745 19.6013 13.0547 19.7211C12.9349 19.8409 12.875 19.9894 12.875 20.1666C12.875 20.3438 12.9349 20.4922 13.0547 20.6118C13.1745 20.7315 13.3229 20.7913 13.5 20.7913ZM13.5 17.458H18.5C18.6771 17.458 18.8255 17.3981 18.9453 17.2782C19.0651 17.1584 19.125 17.0099 19.125 16.8327C19.125 16.6556 19.0651 16.5071 18.9453 16.3875C18.8255 16.2678 18.6771 16.208 18.5 16.208H13.5C13.3229 16.208 13.1745 16.2679 13.0547 16.3878C12.9349 16.5076 12.875 16.6561 12.875 16.8333C12.875 17.0104 12.9349 17.1588 13.0547 17.2785C13.1745 17.3981 13.3229 17.458 13.5 17.458ZM11.2564 23.9163C10.8355 23.9163 10.4792 23.7705 10.1875 23.4788C9.89583 23.1871 9.75 22.8308 9.75 22.4099V9.58942C9.75 9.16848 9.89583 8.81217 10.1875 8.52051C10.4792 8.22884 10.8355 8.08301 11.2564 8.08301H17.2516C17.4548 8.08301 17.6485 8.12201 17.8327 8.20001C18.0169 8.27799 18.1773 8.38536 18.3141 8.52211L21.8109 12.0189C21.9476 12.1556 22.055 12.3161 22.133 12.5003C22.211 12.6844 22.25 12.8781 22.25 13.0814V22.4099C22.25 22.8308 22.1041 23.1871 21.8125 23.4788C21.5208 23.7705 21.1645 23.9163 20.7435 23.9163H11.2564ZM17.25 12.333V9.33299H11.2564C11.1923 9.33299 11.1335 9.3597 11.0801 9.41311C11.0267 9.46654 11 9.52531 11 9.58942V22.4099C11 22.474 11.0267 22.5328 11.0801 22.5862C11.1335 22.6396 11.1923 22.6663 11.2564 22.6663H20.7435C20.8077 22.6663 20.8664 22.6396 20.9199 22.5862C20.9733 22.5328 21 22.474 21 22.4099V13.083H17.9999C17.7874 13.083 17.6093 13.0111 17.4656 12.8673C17.3219 12.7236 17.25 12.5455 17.25 12.333Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

+18 -3
View File
@@ -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";
+14 -9
View File
@@ -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";
+17 -2
View File
@@ -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";
+6 -1
View File
@@ -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, youll 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";
+1 -1
View File
@@ -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:";
+5
View File
@@ -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";
+21 -16
View File
@@ -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?";
+28
View File
@@ -26,6 +26,34 @@
</style>
</head>
<body>
<div>
<p>
<b>Version 2.10.0</b>
</p>
<p>
<b>Neue Funktionen</b>
<ul>
<li/>Der neue Nachrichteneditor: Beim Schreiben von Nachrichten kannst Du jetzt sehr einfach Textformatierungen verwenden.
</ul>
</p>
<p>
<b>Verbesserungen</b>
<ul>
<li/>Die Darstellung der Raumübersicht wurde überarbeitet und verbessert.
<li/>Das Filterverhalten in der Raumübersicht wurde überarbeitet und verbessert.
<li/>Übersetzungen wurden hinzugefügt.
</ul>
</p>
<p>
<b>Behobene Bugs</b>
<ul>
<li/>Du kannst jetzt mehr Sonderzeichen bei der Erstellung eines Passworts verwenden.
</ul>
</p>
</div>
<div>
<p>
<b>Version 2.9.1</b>
+88
View File
@@ -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Спасибо за терпение.";
+5
View File
@@ -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 %@?";
+28
View File
@@ -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";
+30 -25
View File
@@ -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. Ви впевнені, що хочете запросити %@ до %@?";
+67 -7
View File
@@ -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")
}
+21 -1
View File
@@ -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")
+1 -1
View File
@@ -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)
@@ -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?
@@ -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()
}
@@ -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.
@@ -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)")
}
@@ -129,23 +129,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
}
- (NSArray<id<MXRoomSummaryProtocol>> *)favoriteCellDataArray
{
// bwi: for personal notes room
NSMutableArray<id<MXRoomSummaryProtocol>> *filteredArray = [NSMutableArray arrayWithArray:self.recentsListService.favoritedRoomListData.rooms];
if( _recentsDataSourceMode == RecentsDataSourceModeFavourites) {
PersonalNotesDefaultService *service = [[PersonalNotesDefaultService alloc] initWithMxSession:self.mxSession];
PersonalNotesSettings *settings = [[PersonalNotesSettings alloc] init];
if ([service personalNotesRoomId] && settings.personalNotesVisible) {
MXRoom* room = [self.mxSession roomWithRoomId:[service personalNotesRoomId]];
if (room) {
MXRoomSummary *summary = [self.mxSession roomSummaryWithRoomId:[service personalNotesRoomId]];
[filteredArray insertObject:summary atIndex:0];
}
}
}
return filteredArray;
// bwi #4802: for personal notes room
return [self filteredRoomCellDataArray:self.recentsListService.favoritedRoomListData.rooms];
}
- (NSArray<id<MXRoomSummaryProtocol>> *)peopleCellDataArray
{
@@ -153,17 +138,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
}
- (NSArray<id<MXRoomSummaryProtocol>> *)conversationCellDataArray
{
// bwi: for personal notes room
NSMutableArray<id<MXRoomSummaryProtocol>> *filteredArray = [NSMutableArray arrayWithCapacity:self.recentsListService.conversationRoomListData.rooms.count];
for ( id<MXRoomSummaryProtocol> object in self.recentsListService.conversationRoomListData.rooms) {
MXRoom* room = [self.mxSession roomWithRoomId:object.roomId];
if (!room.isPersonalNotesRoom) {
[filteredArray addObject:object];
}
}
return filteredArray;
// bwi #4802: for personal notes room
return [self filteredRoomCellDataArray:self.recentsListService.conversationRoomListData.rooms];
}
- (NSArray<id<MXRoomSummaryProtocol>> *)lowPriorityCellDataArray
{
@@ -179,26 +155,28 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
}
- (NSArray<id<MXRoomSummaryProtocol>> *)breadcrumbsRoomCellDataArray
{
// bwi: for personal notes room
NSMutableArray<id<MXRoomSummaryProtocol>> *filteredArray = [NSMutableArray arrayWithCapacity:self.recentsListService.breadcrumbsRoomListData.rooms.count];
for ( id<MXRoomSummaryProtocol> object in self.recentsListService.breadcrumbsRoomListData.rooms) {
MXRoom* room = [self.mxSession roomWithRoomId:object.roomId];
if (!room.isPersonalNotesRoom) {
[filteredArray addObject:object];
}
}
return filteredArray;
// bwi #4802: for personal notes room
return [self filteredRoomCellDataArray:self.recentsListService.breadcrumbsRoomListData.rooms];
}
- (NSArray<id<MXRoomSummaryProtocol>> *)allChatsRoomCellDataArray
{
// bwi: for personal notes room
NSMutableArray<id<MXRoomSummaryProtocol>> *filteredArray = [NSMutableArray arrayWithCapacity:self.recentsListService.allChatsRoomListData.rooms.count];
// bwi #4802: for personal notes room
return [self filteredRoomCellDataArray:self.recentsListService.allChatsRoomListData.rooms];
}
- (NSArray<id<MXRoomSummaryProtocol>> *)filteredRoomCellDataArray:(NSArray<id<MXRoomSummaryProtocol>> *)arrayToFilter {
// bwi: #4802 for personal notes room
NSMutableArray<id<MXRoomSummaryProtocol>> *filteredArray = [NSMutableArray arrayWithCapacity:arrayToFilter.count];
for ( id<MXRoomSummaryProtocol> object in self.recentsListService.allChatsRoomListData.rooms) {
PersonalNotesSettings *settings = [[PersonalNotesSettings alloc] init];
for ( id<MXRoomSummaryProtocol> object in arrayToFilter) {
MXRoom* room = [self.mxSession roomWithRoomId:object.roomId];
if (!room.isPersonalNotesRoom) {
if (room.isPersonalNotesRoom ) {
if (settings.personalNotesVisible && BWIBuildSettings.shared.bwiPersonalNotesRoom) {
[filteredArray addObject:object];
}
} else {
[filteredArray addObject:object];
}
}
@@ -265,9 +243,6 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
}
}
if (self.recentsListService.shouldShowBWIPersonalNotes) {
[types addObject:@(RecentsDataSourceSectionTypePersonalNotes)];
}
if (self.favoriteCellDataArray.count > 0 || _recentsDataSourceMode == RecentsDataSourceModeFavourites)
{
@@ -716,10 +691,6 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
{
count = self.allChatsRoomCellDataArray.count ?: 1;
}
else if (sectionType == RecentsDataSourceSectionTypePersonalNotes)
{
count = 1;
}
// Adjust this count according to the potential dragged cell.
if ([self isMovingCellSection:section])
@@ -744,7 +715,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
(sectionType == RecentsDataSourceSectionTypeInvites && self.recentsDataSourceMode == RecentsDataSourceModeAllChats) ||
(sectionType == RecentsDataSourceSectionTypeAllChats && !self.allChatsFilterOptions.optionsCount) ||
(sectionType == RecentsDataSourceSectionTypeAllChats && self.currentSpace != nil && self.currentSpace.childRoomIds.count == 0) ||
sectionType == RecentsDataSourceSectionTypePersonalNotes || sectionType == RecentsDataSourceSectionTypeFeatureBanner)
sectionType == RecentsDataSourceSectionTypeFeatureBanner)
{
return 0.0;
}
@@ -1284,11 +1255,6 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
summary = self.allChatsRoomCellDataArray[cellDataIndex];
}
}
else if (sectionType == RecentsDataSourceSectionTypePersonalNotes) {
PersonalNotesDefaultService* service = [[PersonalNotesDefaultService alloc] initWithMxSession:self.mxSession];
summary = [self.mxSession roomWithRoomId:[service personalNotesRoomId]].summary;
}
if (summary)
{
@@ -28,7 +28,6 @@ import Foundation
case serverNotice
case suggestedRooms
case breadcrumbs
case personalNotes
case searchedRoom
case allChats
case unknown
@@ -38,7 +38,7 @@ class RoomActionProvider: RoomActionProviderProtocol {
if BWIBuildSettings.shared.bwiFilteredContextMenu {
if service.roomId == PersonalNotesDefaultService(mxSession: service.session).personalNotesRoomId() {
return UIMenu(children: [
self.notificationsAction
self.hidePersonalNotesAction
])
} else {
return UIMenu(children: [
@@ -110,6 +110,16 @@ class RoomActionProvider: RoomActionProviderProtocol {
self.service.isRoomFavourite = !self.service.isRoomFavourite
}
}
// bwi #4802
private var hidePersonalNotesAction: UIAction {
return UIAction(
title: BWIL10n.homeContextMenuPersonalNotes,
image: UIImage(systemName: "star.slash")) { _ in
PersonalNotesSettings().personalNotesVisible = false
NotificationCenter.default.post(name: AllChatsLayoutSettingsManager.didUpdateSettings, object: self)
}
}
private var lowPriorityAction: UIAction {
return UIAction(
@@ -148,6 +148,10 @@ class AllChatsCoordinator: NSObject, SplitViewMasterCoordinatorProtocol {
self.bwiCheckForMatomoPromt()
BWIAnalytics.sharedTracker.readUserConfig()
if BWIBuildSettings.shared.bwiPersonalNotesRoom {
self.bwiCheckForPersonalNotesRoom()
}
}
func bwiOnUnlockedByPin() {
@@ -301,10 +305,6 @@ class AllChatsCoordinator: NSObject, SplitViewMasterCoordinatorProtocol {
private func addMatrixSessionToAllChatsController(_ matrixSession: MXSession) {
MXLog.debug("[TabBarCoordinator] masterTabBarController.addMatrixSession")
self.allChatsViewController.addMatrixSession(matrixSession)
if BWIBuildSettings.shared.bwiPersonalNotesRoom {
self.bwiCheckForPersonalNotesRoom()
}
}
// TODO: Remove Matrix session handling from the view controller
@@ -388,7 +388,11 @@ class AllChatsCoordinator: NSObject, SplitViewMasterCoordinatorProtocol {
let avatarInsets: UIEdgeInsets = .init(top: 7, left: 7, bottom: 7, right: 7)
var button: UIButton = .init(frame: view.bounds)
button.imageEdgeInsets = avatarInsets
button.setImage(Asset.Images.tabPeople.image, for: .normal)
// bwi: 4704 - ui improvements
let gearshapeImage = Asset.Images.bwiSettingsFilled.image
button.setImage(gearshapeImage, for: .normal)
button.tintColor = ThemeService.shared().theme.tintColor
if BWIBuildSettings.shared.enableSideMenu {
button.menu = avatarMenu
@@ -427,16 +431,18 @@ class AllChatsCoordinator: NSObject, SplitViewMasterCoordinatorProtocol {
}
private func updateAvatarButtonItem() {
MXLog.info("[AllChatsCoordinator] updating avatar button item.")
if let avatar = userAvatarViewData(from: currentMatrixSession) {
if avatarMenuView == nil {
MXLog.warning("[AllChatsCoordinator] updateAvatarButtonItem: avatarMenuView is nil.")
}
avatarMenuView?.fill(with: avatar)
avatarMenuButton?.setImage(nil, for: .normal)
} else {
avatarMenuButton?.setImage(Asset.Images.tabPeople.image, for: .normal)
}
// bwi: 4704 - ui improvements (disable view updates)
// MXLog.info("[AllChatsCoordinator] updating avatar button item.")
// if let avatar = userAvatarViewData(from: currentMatrixSession) {
// if avatarMenuView == nil {
// MXLog.warning("[AllChatsCoordinator] updateAvatarButtonItem: avatarMenuView is nil.")
// }
// avatarMenuView?.fill(with: avatar)
// avatarMenuButton?.setImage(nil, for: .normal)
// } else {
// avatarMenuButton?.setImage(Asset.Images.tabPeople.image, for: .normal)
// }
}
private func showRoom(withId roomId: String, eventId: String? = nil) {
@@ -706,6 +712,7 @@ class AllChatsCoordinator: NSObject, SplitViewMasterCoordinatorProtocol {
}
service.createPersonalNotesRoomIfNeeded()
service.setAsFavoriteIfNeeded()
}
}
@@ -777,6 +784,10 @@ extension AllChatsCoordinator: AllChatsViewControllerDelegate {
self.bwiCheckForMatomoPromt()
BWIAnalytics.sharedTracker.resetMatomo()
if BWIBuildSettings.shared.bwiPersonalNotesRoom {
self.bwiCheckForPersonalNotesRoom()
}
}
func allChatsViewController(_ allChatsViewController: AllChatsViewController, didSelectRoomWithParameters roomNavigationParameters: RoomNavigationParameters, completion: @escaping () -> Void) {
@@ -77,6 +77,9 @@ class AllChatsViewController: HomeViewController {
private var isOnboardingCoordinatorPreparing: Bool = false
// bwi: 4807
private var floatingButton: UIButton?
private var theme: Theme {
ThemeService.shared().theme
}
@@ -92,10 +95,11 @@ class AllChatsViewController: HomeViewController {
}
private func setToolbarHidden(_ isHidden: Bool, animated: Bool) {
UIView.animate(withDuration: animated ? 0.3 : 0) {
self.isToolbarHidden = isHidden
if BWIBuildSettings.shared.enableAllChatsToolbar {
UIView.animate(withDuration: animated ? 0.3 : 0) {
self.isToolbarHidden = isHidden
}
}
}
// MARK: - SplitViewMasterViewControllerProtocol
@@ -117,6 +121,8 @@ class AllChatsViewController: HomeViewController {
private var toolbarHeight: CGFloat = 0
private weak var roomFilterButton: UIButton?
// MARK: - Lifecycle
override func viewDidLoad() {
@@ -135,25 +141,46 @@ class AllChatsViewController: HomeViewController {
toolbarHeight = toolbar.frame.height
emptyViewBottomAnchor = toolbar.topAnchor
// bwi: 4179
if BWIBuildSettings.shared.useNewBumColors { // bwi: #4883
toolbar.tintColor = ThemeService.shared().theme.tintColor
toolbar.barTintColor = ThemeService.shared().theme.backgroundColor
} else {
toolbar.tintColor = theme.colors.accent
}
// bwi: 4807 - hide the toolbar and show a floating button for room create instead
if !BWIBuildSettings.shared.enableAllChatsToolbar {
// no toolbar then use a floating button instead
floatingButton = UIButton(frame: CGRect(x: 0, y: 0, width: 56, height: 56))
updateFloatingButton()
if let floatingButton = floatingButton {
view.addSubview(floatingButton)
}
// set constraint to make the floating button stay in the lower right corner
floatingButton?.translatesAutoresizingMaskIntoConstraints = false
floatingButton?.widthAnchor.constraint(equalToConstant: 56).isActive = true
floatingButton?.heightAnchor.constraint(equalToConstant: 56).isActive = true
floatingButton?.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -16).isActive = true
floatingButton?.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -40).isActive = true
}
if BWIBuildSettings.shared.roomFiltersToggle {
updateNewFilterSearchAndToggleButton()
}
updateUI()
navigationItem.largeTitleDisplayMode = .automatic
navigationController?.navigationBar.prefersLargeTitles = true
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchResultsUpdater = self
searchController.delegate = self
navigationItem.largeTitleDisplayMode = .never
navigationController?.navigationBar.prefersLargeTitles = false
if !BWIBuildSettings.shared.roomFiltersToggle {
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchResultsUpdater = self
searchController.delegate = self
}
NotificationCenter.default.addObserver(self, selector: #selector(self.setupEditOptions), name: AllChatsLayoutSettingsManager.didUpdateSettings, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.updateBadgeButton), name: MXSpaceNotificationCounter.didUpdateNotificationCount, object: nil)
@@ -161,6 +188,76 @@ class AllChatsViewController: HomeViewController {
self.registerThemeServiceDidChangeThemeNotification()
}
// bwi: 4806
private func updateNewFilterSearchAndToggleButton() {
let customHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: recentsTableView.frame.width, height: 50))
let searchBar = UISearchBar(frame: CGRect(x: 8, y: 0, width: customHeaderView.frame.width - 48, height: 50))
let button = UIButton(frame: CGRect(x: customHeaderView.frame.width - 48 + 8, y: 0, width: 40, height: 50))
if ThemeService.shared().isCurrentThemeDark() {
button.setImage(Asset.Images.roomFilterToggleDarkOff.image, for: .normal)
button.setImage(Asset.Images.roomFilterToggleDarkOn.image, for: .selected)
} else {
button.setImage(Asset.Images.roomFilterToggleLightOff.image, for: .normal)
button.setImage(Asset.Images.roomFilterToggleLightOn.image, for: .selected)
}
let settings = AllChatsLayoutSettingsManager.shared.allChatLayoutSettings
let areFiltersVisible = !settings.filters.isEmpty
button.isSelected = !AllChatsLayoutSettingsManager.shared.allChatLayoutSettings.filters.isEmpty
button.addTarget(self, action: #selector(onFilterToggleTapped), for: .touchUpInside)
roomFilterButton = button // keep a reference to handle theme changes
searchBar.placeholder = BWIL10n.allChatsSearchbarPrompt
searchBar.backgroundImage = UIImage() // this hides the separator lines above and below
searchBar.delegate = self
customHeaderView.addSubview(searchBar)
customHeaderView.addSubview(button)
recentsTableView.tableHeaderView = customHeaderView
// set some constraints for landscape and iPad
customHeaderView.translatesAutoresizingMaskIntoConstraints = false
let constraints = [
searchBar.leadingAnchor.constraint(equalTo: customHeaderView.leadingAnchor),
searchBar.centerYAnchor.constraint(equalTo: button.centerYAnchor),
searchBar.widthAnchor.constraint(equalToConstant: 40),
searchBar.heightAnchor.constraint(equalToConstant: 40),
button.leadingAnchor.constraint(equalTo: searchBar.trailingAnchor),
button.trailingAnchor.constraint(equalTo: customHeaderView.trailingAnchor),
button.topAnchor.constraint(equalTo: customHeaderView.topAnchor),
button.bottomAnchor.constraint(equalTo: customHeaderView.bottomAnchor),
customHeaderView.centerXAnchor.constraint(equalTo: recentsTableView.centerXAnchor),
customHeaderView.widthAnchor.constraint(equalTo: recentsTableView.widthAnchor),
customHeaderView.topAnchor.constraint(equalTo: recentsTableView.topAnchor)
]
NSLayoutConstraint.activate(constraints)
}
@objc
func onSearchTextChanged(searchBar: UISearchBar) {
guard let searchText = searchBar.text, !searchText.isEmpty else {
self.dataSource?.search(withPatterns: nil)
return
}
self.dataSource?.search(withPatterns: [searchText])
}
@objc
func onFilterToggleTapped() {
let settings = AllChatsLayoutSettingsManager.shared.allChatLayoutSettings
let areFiltersVisible = !settings.filters.isEmpty
let newSettings = AllChatsLayoutSettings(sections: settings.sections,
filters: areFiltersVisible ? [] : [.unreads, .favourites, .people],
sorting: settings.sorting)
AllChatsLayoutSettingsManager.shared.allChatLayoutSettings = newSettings
Analytics.shared.trackInteraction(areFiltersVisible ? .allChatsFiltersDisabled : .allChatsFiltersEnabled)
roomFilterButton?.isSelected = !AllChatsLayoutSettingsManager.shared.allChatLayoutSettings.filters.isEmpty
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
@@ -172,8 +269,24 @@ class AllChatsViewController: HomeViewController {
self.toolbar.tintColor = theme.colors.accent
}
if self.navigationItem.searchController == nil {
self.navigationItem.searchController = searchController
// bwi: 4807 - hide the toolbar and show a floating button for room create instead
if !BWIBuildSettings.shared.enableAllChatsToolbar {
toolbar.transform = CGAffineTransform(translationX: 0, y: 2 * toolbarHeight)
self.view.layoutIfNeeded()
}
if BWIBuildSettings.shared.roomFiltersToggle {
if ThemeService.shared().isCurrentThemeDark() {
roomFilterButton?.setImage(Asset.Images.roomFilterToggleDarkOff.image, for: .normal)
roomFilterButton?.setImage(Asset.Images.roomFilterToggleDarkOn.image, for: .selected)
} else {
roomFilterButton?.setImage(Asset.Images.roomFilterToggleLightOff.image, for: .normal)
roomFilterButton?.setImage(Asset.Images.roomFilterToggleLightOn.image, for: .selected)
}
} else {
if self.navigationItem.searchController == nil {
self.navigationItem.searchController = searchController
}
}
NotificationCenter.default.addObserver(self, selector: #selector(self.spaceListDidChange), name: MXSpaceService.didInitialise, object: nil)
@@ -217,7 +330,7 @@ class AllChatsViewController: HomeViewController {
coordinator.animate { context in
self.recentsTableView?.tableHeaderView?.layoutIfNeeded()
self.recentsTableView?.tableHeaderView = self.recentsTableView?.tableHeaderView
// self.recentsTableView?.tableHeaderView = self.recentsTableView?.tableHeaderView
}
}
@@ -319,7 +432,6 @@ class AllChatsViewController: HomeViewController {
RecentsDataSourceSectionType.serverNotice.rawValue,
RecentsDataSourceSectionType.suggestedRooms.rawValue,
RecentsDataSourceSectionType.breadcrumbs.rawValue,
RecentsDataSourceSectionType.personalNotes.rawValue,
RecentsDataSourceSectionType.featureBanner.rawValue
]
}
@@ -343,8 +455,20 @@ class AllChatsViewController: HomeViewController {
alert.addAction(UIAlertAction(title: BWIL10n.bwiAnalyticsAlertInfoButton,
style: .default,
handler: { [self] action in
if let url = URL(string: BWIBuildSettings.shared.applicationPrivacyPolicyWithMatomoSectionUrlString) {
UIApplication.shared.open(url)
if let defaultURL = URL(string: BWIBuildSettings.shared.applicationPrivacyPolicyWithMatomoSectionUrlString) {
if BWIBuildSettings.shared.bwiUseWellKnownPrivacyPolicyLink {
guard let wellKnownDataPrivacyURL = URL(string: self.mainSession.homeserverWellknown.dataPrivacyURL() ?? ""), let defaultHost = defaultURL.host else {
UIApplication.shared.open(defaultURL)
return
}
if !wellKnownDataPrivacyURL.absoluteString.contains(defaultHost) {
UIApplication.shared.open(wellKnownDataPrivacyURL)
} else {
UIApplication.shared.open(defaultURL)
}
} else {
UIApplication.shared.open(defaultURL)
}
}
showMatomoConsentAlertOnCloseModal = true
}))
@@ -541,14 +665,16 @@ class AllChatsViewController: HomeViewController {
override func shouldShowEmptyView() -> Bool {
let shouldShowEmptyView = super.shouldShowEmptyView() && !AllChatsLayoutSettingsManager.shared.hasAnActiveFilter
if shouldShowEmptyView {
self.navigationItem.searchController = nil
navigationItem.largeTitleDisplayMode = .never
} else {
self.navigationItem.searchController = searchController
navigationItem.largeTitleDisplayMode = .automatic
if !BWIBuildSettings.shared.roomFiltersToggle {
if shouldShowEmptyView {
self.navigationItem.searchController = nil
navigationItem.largeTitleDisplayMode = .never
} else {
self.navigationItem.searchController = searchController
navigationItem.largeTitleDisplayMode = .automatic
}
}
return shouldShowEmptyView
}
@@ -580,6 +706,17 @@ class AllChatsViewController: HomeViewController {
} else {
self.navigationController?.toolbar?.tintColor = theme.colors.accent
}
// bwi: 4807
updateFloatingButton()
}
private func updateFloatingButton() {
if ThemeService.shared().isCurrentThemeDark() {
floatingButton?.setImage(Asset.Images.buttonNewDark.image, for: .normal)
} else {
floatingButton?.setImage(Asset.Images.buttonNewLight.image, for: .normal)
}
}
// MARK: - Private
@@ -589,10 +726,10 @@ class AllChatsViewController: HomeViewController {
return
}
tableView.tableHeaderView = tableHeadeView
tableView.tableHeaderView?.widthAnchor.constraint(equalTo: tableView.widthAnchor).isActive = true
tableView.tableHeaderView?.layoutIfNeeded()
tableView.tableHeaderView = self.recentsTableView?.tableHeaderView
// tableView.tableHeaderView = tableHeadeView
// tableView.tableHeaderView?.widthAnchor.constraint(equalTo: tableView.widthAnchor).isActive = true
// tableView.tableHeaderView?.layoutIfNeeded()
// tableView.tableHeaderView = self.recentsTableView?.tableHeaderView
}
@objc private func setupEditOptions() {
@@ -611,15 +748,31 @@ class AllChatsViewController: HomeViewController {
self.title = currentSpace?.summary?.displayName ?? VectorL10n.allChatsTitle
setupEditOptions()
updateToolbar(with: editActionProvider.updateMenu(with: mainSession, parentSpace: currentSpace, completion: { [weak self] menu in
self?.updateToolbar(with: menu)
}))
let menu = editActionProvider.updateMenu(with: mainSession, parentSpace: currentSpace, completion: { [weak self] menu in
if BWIBuildSettings.shared.enableAllChatsToolbar {
self?.updateToolbar(with: menu)
} else {
}
})
if BWIBuildSettings.shared.enableAllChatsToolbar {
updateToolbar(with: menu)
} else {
updateFloatingButton()
self.floatingButton?.menu = menu
self.floatingButton?.showsMenuAsPrimaryAction = true
}
updateEmptyView()
updateBadgeButton()
}
private func updateRightNavigationItem(with menu: UIMenu) {
self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(systemName: "ellipsis.circle"), menu: menu)
// bwi 4704 - hide right navigation bar button
if BWIBuildSettings.shared.showAllChatsFilterMenu {
self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(systemName: "ellipsis.circle"), menu: menu)
}
}
private lazy var spacesButton: BadgedBarButtonItem = {
@@ -846,7 +999,7 @@ extension AllChatsViewController: UISearchResultsUpdating {
self.dataSource?.search(withPatterns: nil)
return
}
self.dataSource?.search(withPatterns: [searchText])
}
}
@@ -859,6 +1012,17 @@ extension AllChatsViewController: UISearchControllerDelegate {
}
}
extension AllChatsViewController {
override func searchBar(_ searchBar: UISearchBar, textDidChange: String) {
guard let searchText = searchBar.text, !searchText.isEmpty else {
self.dataSource?.search(withPatterns: nil)
return
}
self.dataSource?.search(withPatterns: [searchText])
}
}
// MARK: - UIAdaptivePresentationControllerDelegate
extension AllChatsViewController: UIAdaptivePresentationControllerDelegate {
+2 -4
View File
@@ -398,7 +398,6 @@
|| (sectionType == RecentsDataSourceSectionTypePeople && !recentsDataSource.recentsListService.peopleRoomListData.counts.numberOfRooms)
|| (sectionType == RecentsDataSourceSectionTypeSecureBackupBanner)
|| (sectionType == RecentsDataSourceSectionTypeCrossSigningBanner)
|| (sectionType == RecentsDataSourceSectionTypePersonalNotes)
)
{
return [recentsDataSource tableView:tableView cellForRowAtIndexPath:indexPath];
@@ -502,8 +501,7 @@
RecentsDataSourceSectionType sectionType = [recentsDataSource.sections sectionTypeForSectionIndex:indexPath.section];
if ((sectionType == RecentsDataSourceSectionTypeConversation && !recentsDataSource.recentsListService.conversationRoomListData.counts.numberOfRooms)
|| (sectionType == RecentsDataSourceSectionTypePeople && !recentsDataSource.recentsListService.peopleRoomListData.counts.numberOfRooms)
|| (sectionType == RecentsDataSourceSectionTypePersonalNotes))
|| (sectionType == RecentsDataSourceSectionTypePeople && !recentsDataSource.recentsListService.peopleRoomListData.counts.numberOfRooms))
{
return [recentsDataSource cellHeightAtIndexPath:indexPath];
}
@@ -582,7 +580,7 @@
{
[self showCrossSigningSetup];
}
else if (sectionType == RecentsDataSourceSectionTypeAllChats || sectionType == RecentsDataSourceSectionTypePersonalNotes)
else if (sectionType == RecentsDataSourceSectionTypeAllChats)
{
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
}
@@ -305,15 +305,5 @@
*/
- (void)showAuthenticationFallBackView;
#pragma mark - Device rehydration
/**
Call this method at an appropriate time to attempt rehydrating from an existing dehydrated device
@param keyData Secret key data
@param credentials Account credentials
*/
- (void)attemptDeviceRehydrationWithKeyData:(NSData *)keyData credentials:(MXCredentials *)credentials;
@end
@@ -1513,68 +1513,6 @@
[self _createAccountWithCredentials:credentials];
}
- (void)attemptDeviceRehydrationWithKeyData:(NSData *)keyData
credentials:(MXCredentials *)credentials
{
[self attemptDeviceRehydrationWithKeyData:keyData
credentials:credentials
retry:YES];
}
- (void)attemptDeviceRehydrationWithKeyData:(NSData *)keyData
credentials:(MXCredentials *)credentials
retry:(BOOL)retry
{
MXLogDebug(@"[MXKAuthenticationViewController] attemptDeviceRehydration: starting device rehydration");
if (keyData == nil)
{
MXLogError(@"[MXKAuthenticationViewController] attemptDeviceRehydration: no key provided for device rehydration");
[self _createAccountWithCredentials:credentials];
return;
}
MXRestClient *mxRestClient = [[MXRestClient alloc] initWithCredentials:credentials andOnUnrecognizedCertificateBlock:^BOOL(NSData *certificate) {
return NO;
} andPersistentTokenDataHandler:^(void (^handler)(NSArray<MXCredentials *> *credentials, void (^completion)(BOOL didUpdateCredentials))) {
[[MXKAccountManager sharedManager] readAndWriteCredentials:handler];
} andUnauthenticatedHandler: nil];
MXWeakify(self);
[[MXKAccountManager sharedManager].dehydrationService rehydrateDeviceWithMatrixRestClient:mxRestClient dehydrationKey:keyData success:^(NSString * deviceId) {
MXStrongifyAndReturnIfNil(self);
if (deviceId)
{
MXLogDebug(@"[MXKAuthenticationViewController] attemptDeviceRehydration: device %@ rehydrated successfully.", deviceId);
credentials.deviceId = deviceId;
}
else
{
MXLogDebug(@"[MXKAuthenticationViewController] attemptDeviceRehydration: device rehydration has been canceled.");
}
[self _createAccountWithCredentials:credentials];
} failure:^(NSError *error) {
MXStrongifyAndReturnIfNil(self);
if (retry)
{
MXLogErrorDetails(@"[MXKAuthenticationViewController] attemptDeviceRehydration: device rehydration failed due to error: Retrying", @{
@"error": error ?: @"unknown"
});
[self attemptDeviceRehydrationWithKeyData:keyData credentials:credentials retry:NO];
return;
}
MXLogErrorDetails(@"[MXKAuthenticationViewController] attemptDeviceRehydration: device rehydration failed due to error", @{
@"error": error ?: @"unknown"
});
[self _createAccountWithCredentials:credentials];
}];
}
- (void)_createAccountWithCredentials:(MXCredentials *)credentials
{
MXKAccount *account = [[MXKAccount alloc] initWithCredentials:credentials];
@@ -375,13 +375,6 @@ typedef BOOL (^MXKAccountOnCertificateChange)(MXKAccount *mxAccount, NSData *cer
#pragma mark - Sync filter
/**
Call this method at an appropriate time to attempt dehydrating to a new backup device
*/
- (void)attemptDeviceDehydrationWithKeyData:(NSData *)keyData
success:(void (^)(void))success
failure:(void (^)(NSError *error))failure;
/**
Handle unauthenticated errors from the server triggering hard/soft logouts as appropriate.
*/
@@ -1727,70 +1727,6 @@ static NSArray<NSNumber*> *initialSyncSilentErrorsHTTPStatusCodes;
}];
}
- (void)attemptDeviceDehydrationWithKeyData:(NSData *)keyData
success:(void (^)(void))success
failure:(void (^)(NSError *error))failure
{
[self attemptDeviceDehydrationWithKeyData:keyData retry:YES success:success failure:failure];
}
- (void)attemptDeviceDehydrationWithKeyData:(NSData *)keyData
retry:(BOOL)retry
success:(void (^)(void))success
failure:(void (^)(NSError *error))failure
{
if (keyData == nil)
{
MXLogWarning(@"[MXKAccount] attemptDeviceDehydrationWithRetry: no key provided for device dehydration");
if (failure)
{
failure(nil);
}
return;
}
if (![mxSession.crypto.crossSigning isKindOfClass:[MXLegacyCrossSigning class]]) {
MXLogFailure(@"Device dehydratation is currently only supported by legacy cross signing, add support to all implementations");
if (failure)
{
failure(nil);
}
return;
}
MXLegacyCrossSigning *crossSigning = (MXLegacyCrossSigning *)mxSession.crypto.crossSigning;;
MXLogDebug(@"[MXKAccount] attemptDeviceDehydrationWithRetry: starting device dehydration");
[[MXKAccountManager sharedManager].dehydrationService dehydrateDeviceWithMatrixRestClient:mxRestClient crossSigning:crossSigning dehydrationKey:keyData success:^(NSString *deviceId) {
MXLogDebug(@"[MXKAccount] attemptDeviceDehydrationWithRetry: device successfully dehydrated");
if (success)
{
success();
}
} failure:^(NSError *error) {
if (retry)
{
[self attemptDeviceDehydrationWithKeyData:keyData retry:NO success:success failure:failure];
MXLogErrorDetails(@"[MXKAccount] attemptDeviceDehydrationWithRetry: device dehydration failed due to error: Retrying.", @{
@"error": error ?: @"unknown"
});
}
else
{
MXLogErrorDetails(@"[MXKAccount] attemptDeviceDehydrationWithRetry: device dehydration failed due to error", @{
@"error": error ?: @"unknown"
});
if (failure)
{
failure(error);
}
}
}];
}
- (void)onMatrixSessionStateChange
{
// Check if pause has been requested
@@ -104,8 +104,6 @@ extern NSString *const MXKAccountManagerDataType;
*/
@property (nonatomic) BOOL isPushAvailable;
@property (nonatomic, readonly) MXDehydrationService *dehydrationService;
/**
Retrieve the MXKAccounts manager.
@@ -71,7 +71,6 @@ NSString *const MXKAccountManagerDataType = @"org.matrix.kit.MXKAccountManagerDa
if (self)
{
_storeClass = [MXFileStore class];
_dehydrationService = [MXDehydrationService new];
_savingAccountsEnabled = YES;
// Migrate old account file to new format
@@ -41,8 +41,14 @@
}
else
{
title = [error.userInfo valueForKey:NSLocalizedFailureReasonErrorKey];
message = [error.userInfo valueForKey:NSLocalizedDescriptionKey];
// bwi: #4857 translate invalid password error message
if ([error.domain isEqualToString:kMXNSErrorDomain] && [[error.userInfo valueForKey:NSLocalizedDescriptionKey] isEqualToString: @"Invalid username or password"]) {
title = [error.userInfo valueForKey:NSLocalizedFailureReasonErrorKey];
message = [BWIL10n bwiErrorInvalidPassword];
} else {
title = [error.userInfo valueForKey:NSLocalizedFailureReasonErrorKey];
message = [error.userInfo valueForKey:NSLocalizedDescriptionKey];
}
if (!title)
{
@@ -830,38 +830,37 @@ static NSString *const kRepliedTextPattern = @"<mx-reply>.*<blockquote>.*<br>(.*
}
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;
}
@@ -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
+5 -3
View File
@@ -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
+4 -2
View File
@@ -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
@@ -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
@@ -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)
}
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
}
@@ -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
@@ -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))
})
@@ -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()
@@ -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;
+97 -12
View File
@@ -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
+7 -17
View File
@@ -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;
+1 -1
View File
@@ -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"
+2 -1
View File
@@ -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
}
}
+4 -2
View File
@@ -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
+3 -1
View File
@@ -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
+1
View File
@@ -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/
@@ -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
}
@@ -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, {}))
}
}
@@ -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) {
@@ -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 {
@@ -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()
}
}
}
@@ -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,
@@ -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)
}
}
@@ -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
}
}
}
@@ -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))
}
@@ -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
@@ -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,
@@ -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))
}
@@ -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?()
})
}
}
@@ -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.
+20 -9
View File
@@ -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)
}
}
@@ -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)
@@ -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()
}
}

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