Merge branch 'release/v2.10.0'
@@ -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
|
||||
|
||||
@@ -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)
|
||||
===================================================
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -16,5 +16,5 @@
|
||||
//
|
||||
|
||||
// Version
|
||||
MARKETING_VERSION = 2.9.1
|
||||
MARKETING_VERSION = 2.10.0
|
||||
CURRENT_PROJECT_VERSION = 20220714163152
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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|
|
||||
|
||||
@@ -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 |
|
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 |
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -748,6 +748,9 @@ Tap the + to start adding people.";
|
||||
"settings_three_pids_management_information_part1" = "Manage which email addresses or phone numbers you can use to log in or recover your account here. Control who can find you in ";
|
||||
"settings_three_pids_management_information_part2" = "Discovery";
|
||||
"settings_three_pids_management_information_part3" = ".";
|
||||
"settings_manage_account_title" = "Account";
|
||||
"settings_manage_account_action" = "Manage account";
|
||||
"settings_manage_account_description" = "Manage your account at %@";
|
||||
|
||||
"settings_confirm_media_size" = "Confirm size when sending";
|
||||
"settings_confirm_media_size_description" = "When this is on, you’ll be asked to confirm what size images and videos will be sent as.";
|
||||
@@ -964,6 +967,8 @@ Tap the + to start adding people.";
|
||||
"manage_session_trusted" = "Trusted by you";
|
||||
"manage_session_not_trusted" = "Not trusted";
|
||||
"manage_session_sign_out" = "Sign out of this session";
|
||||
"manage_session_redirect" = "You will be redirected to your server's authentication provider to complete sign out.";
|
||||
"manage_session_redirect_error" = "Functionality currently unavailable. Please contact your homeserver admin";
|
||||
"manage_session_rename" = "Rename session";
|
||||
"manage_session_sign_out_other_sessions" = "Sign out of all other sessions";
|
||||
// User sessions management
|
||||
@@ -2279,7 +2284,7 @@ Tap the + to start adding people.";
|
||||
|
||||
// MARK: - All Chats
|
||||
|
||||
"all_chats_title" = "All chats";
|
||||
"all_chats_title" = "Chats";
|
||||
"all_chats_section_title" = "Chats";
|
||||
"all_chats_edit_layout" = "Layout preferences";
|
||||
"all_chats_edit_layout_recents" = "Recents";
|
||||
|
||||
@@ -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:";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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?";
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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Спасибо за терпение.";
|
||||
|
||||
@@ -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 %@?";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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. Ви впевнені, що хочете запросити %@ до %@?";
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||