Merge branch 'develop' of https://github.com/vector-im/element-ios into langleyd/4776_extract_swiftui

This commit is contained in:
David Langley
2021-09-02 10:14:11 +01:00
63 changed files with 429 additions and 842 deletions

View File

@@ -1,3 +1,34 @@
## Changes in 1.5.2 (2021-08-27)
✨ Features
- Account Notification Settings: Enable/disable notification settings (Default, Mentions & Keywords and Other) and edit Keywords. ([#4467](https://github.com/vector-im/element-ios/issues/4467))
- Implemented dialogs to inform users about Element iOS11 deprecation. ([#4693](https://github.com/vector-im/element-ios/issues/4693))
🙌 Improvements
- Upgrade MatrixKit version ([v0.15.8](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.15.8)).
- Popping the user back to the home screen after leaving a room. ([#1482](https://github.com/vector-im/element-ios/issues/1482))
- Notifications: Replace "Message" fallback with "Notification" as the event may not be a message. ([#4132](https://github.com/vector-im/element-ios/issues/4132))
- MXSessionState: Use Swifty versions. ([#4471](https://github.com/vector-im/element-ios/issues/4471))
- Notifications: Show the body of all message event types. ([#4653](https://github.com/vector-im/element-ios/issues/4653))
- Notifications: Replies now hide the referenced content. ([#4660](https://github.com/vector-im/element-ios/issues/4660))
- Room Notification Settings: This screen is now implemented in SwiftUI for users on iOS14 or above. ([#4669](https://github.com/vector-im/element-ios/issues/4669))
🐛 Bugfixes
- Fixed flickering voice message cells while being sent. ([#4714](https://github.com/vector-im/element-ios/issues/4714))
- Fastfile: Update build number in AppVersion.xcconfig instead of AppIdentifiers.xcconfig. ([#4726](https://github.com/vector-im/element-ios/issues/4726))
- Disabled the create room button while creating a room, preventing duplicates from being created. ([#4746](https://github.com/vector-im/element-ios/issues/4746))
- Fixed cached callbacks race condition, serialized all async operations, properly cleaning up callbacks on failure. ([#4748](https://github.com/vector-im/element-ios/issues/4748))
- Notification Settings: Keywords Notification Setting should be "On" by default. ([#4759](https://github.com/vector-im/element-ios/issues/4759))
🧱 Build
- Support building Ad-hoc alpha release on pull request (#4635). ([#4635](https://github.com/vector-im/element-ios/issues/4635))
- Move app version from AppIdentifiers.xcconfig into a dedicated config file (#4715). ([#4715](https://github.com/vector-im/element-ios/issues/4715))
## Changes in 1.5.1 (2021-08-12)
🐛 Bugfixes

View File

@@ -15,5 +15,5 @@
//
// Version
MARKETING_VERSION = 1.5.2
CURRENT_PROJECT_VERSION = 1.5.2
MARKETING_VERSION = 1.5.3
CURRENT_PROJECT_VERSION = 1.5.3

View File

@@ -25,7 +25,7 @@
KEYCHAIN_ACCESS_GROUP = $(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER).keychain.shared
// Build settings
IPHONEOS_DEPLOYMENT_TARGET = 11.0
IPHONEOS_DEPLOYMENT_TARGET = 12.1
SDKROOT = iphoneos
TARGETED_DEVICE_FAMILY = 1,2
SWIFT_VERSION = 5.3.1
@@ -45,4 +45,4 @@ CLANG_ANALYZER_NONNULL = YES
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE
CLANG_ENABLE_MODULES = YES
CLANG_ENABLE_OBJC_ARC = YES
CLANG_ENABLE_OBJC_ARC = YES

View File

@@ -1,5 +1,7 @@
source 'https://cdn.cocoapods.org/'
# Uncomment this line to define a global platform for your project
platform :ios, '11.0'
platform :ios, '12.1'
# Use frameforks to allow usage of pod written in Swift (like PiwikTracker)
use_frameworks!
@@ -11,7 +13,7 @@ use_frameworks!
# - `{ {kit spec hash} => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for each 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
# $matrixKitVersion = '= 0.15.7'
# $matrixKitVersion = '= 0.15.8'
# $matrixKitVersion = :local
$matrixKitVersion = {'develop' => 'develop'}
@@ -70,7 +72,7 @@ abstract_target 'RiotPods' do
pod 'SwiftJWT', '~> 3.6.200'
pod 'SideMenu', '~> 6.5'
pod 'DSWaveformImage', '~> 6.1.1'
pod 'ffmpeg-kit-ios-audio', '~> 4.4.LTS'
pod 'ffmpeg-kit-ios-audio', '~> 4.4'
pod 'FLEX', '~> 4.4.1', :configurations => ['Debug']

View File

@@ -58,29 +58,29 @@ PODS:
- MatomoTracker (7.4.1):
- MatomoTracker/Core (= 7.4.1)
- MatomoTracker/Core (7.4.1)
- MatrixKit (0.15.7):
- MatrixKit (0.15.8):
- Down (~> 0.11.0)
- DTCoreText (~> 1.6.25)
- HPGrowingTextView (~> 1.1)
- libPhoneNumber-iOS (~> 0.9.13)
- MatrixKit/Core (= 0.15.7)
- MatrixSDK (= 0.19.7)
- MatrixKit/Core (0.15.7):
- MatrixKit/Core (= 0.15.8)
- MatrixSDK (= 0.19.8)
- MatrixKit/Core (0.15.8):
- Down (~> 0.11.0)
- DTCoreText (~> 1.6.25)
- HPGrowingTextView (~> 1.1)
- libPhoneNumber-iOS (~> 0.9.13)
- MatrixSDK (= 0.19.7)
- MatrixSDK (0.19.7):
- MatrixSDK/Core (= 0.19.7)
- MatrixSDK/Core (0.19.7):
- MatrixSDK (= 0.19.8)
- MatrixSDK (0.19.8):
- MatrixSDK/Core (= 0.19.8)
- MatrixSDK/Core (0.19.8):
- AFNetworking (~> 4.0.0)
- GZIP (~> 1.3.0)
- libbase58 (~> 0.1.4)
- OLMKit (~> 3.2.4)
- Realm (= 10.7.6)
- SwiftyBeaver (= 1.9.5)
- MatrixSDK/JingleCallStack (0.19.7):
- MatrixSDK/JingleCallStack (0.19.8):
- JitsiMeetSDK (= 3.5.0)
- MatrixSDK/Core
- OLMKit (3.2.4):
@@ -116,7 +116,7 @@ PODS:
DEPENDENCIES:
- DGCollectionViewLeftAlignFlowLayout (~> 1.0.4)
- DSWaveformImage (~> 6.1.1)
- ffmpeg-kit-ios-audio (~> 4.4.LTS)
- ffmpeg-kit-ios-audio (~> 4.4)
- FLEX (~> 4.4.1)
- FlowCommoniOS (~> 1.10.0)
- GBDeviceInfo (~> 6.6.0)
@@ -124,7 +124,7 @@ DEPENDENCIES:
- KeychainAccess (~> 4.2.2)
- KTCenterFlowLayout (~> 1.3.1)
- MatomoTracker (~> 7.4.1)
- MatrixKit (= 0.15.7)
- MatrixKit (= 0.15.8)
- MatrixSDK
- MatrixSDK/JingleCallStack
- OLMKit
@@ -204,8 +204,8 @@ SPEC CHECKSUMS:
LoggerAPI: ad9c4a6f1e32f518fdb43a1347ac14d765ab5e3d
Logging: beeb016c9c80cf77042d62e83495816847ef108b
MatomoTracker: 24a846c9d3aa76933183fe9d47fd62c9efa863fb
MatrixKit: 5939d1b63bad3e7f709534a8f105b69f84728591
MatrixSDK: c0bbec5b67cc8771cffdf3b494d622bce0a51ceb
MatrixKit: 2945ade22970747defcc4d564cb0c7aedbd4019d
MatrixSDK: 4d4679b499b4802a11a90b3652f83be496bfaec1
OLMKit: 2d73cd67d149b5c3e3a8eb8ecae93d0b429d8a02
ReadMoreTextView: 19147adf93abce6d7271e14031a00303fe28720d
Realm: ed860452717c8db8f4bf832b6807f7f2ce708839
@@ -219,6 +219,6 @@ SPEC CHECKSUMS:
zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb
PODFILE CHECKSUM: 605b63b9968e2916d998f4769f162b4b7c2a2577
PODFILE CHECKSUM: 81db0a2f4da6c24be3bfdd2c2de5b57e954f133e
COCOAPODS: 1.10.1
COCOAPODS: 1.10.2

View File

@@ -4,8 +4,7 @@
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
runPostActionsOnFailure = "NO">
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"

View File

@@ -21,17 +21,12 @@ import UIKit
/// Returns 'true' if the current device has a notch
var hasNotch: Bool {
if #available(iOS 11.0, *) {
// Case 1: Portrait && top safe area inset >= 44
let case1 = !UIDevice.current.orientation.isLandscape && (UIApplication.shared.keyWindow?.safeAreaInsets.top ?? 0) >= 44
// Case 2: Lanscape && left/right safe area inset > 0
let case2 = UIDevice.current.orientation.isLandscape && ((UIApplication.shared.keyWindow?.safeAreaInsets.left ?? 0) > 0 || (UIApplication.shared.keyWindow?.safeAreaInsets.right ?? 0) > 0)
return case1 || case2
} else {
// Fallback on earlier versions
return false
}
// Case 1: Portrait && top safe area inset >= 44
let case1 = !UIDevice.current.orientation.isLandscape && (UIApplication.shared.keyWindow?.safeAreaInsets.top ?? 0) >= 44
// Case 2: Lanscape && left/right safe area inset > 0
let case2 = UIDevice.current.orientation.isLandscape && ((UIApplication.shared.keyWindow?.safeAreaInsets.left ?? 0) > 0 || (UIApplication.shared.keyWindow?.safeAreaInsets.right ?? 0) > 0)
return case1 || case2
}
/// Returns if the device is a Phone

View File

@@ -22,10 +22,8 @@ extension UITableView {
/// Returns safe area insetted separator inset. Should only be used when custom constraints on custom table view cells are being set according to separator insets.
@objc var vc_separatorInset: UIEdgeInsets {
var result = separatorInset
if #available(iOS 11.0, *) {
result.left -= self.safeAreaInsets.left
result.right -= self.safeAreaInsets.right
}
result.left -= self.safeAreaInsets.left
result.right -= self.safeAreaInsets.right
return result
}

View File

@@ -26,10 +26,8 @@ extension UITableViewCell {
/// Returns safe area insetted separator inset. Should only be used when custom constraints on custom table view cells are being set according to separator insets.
@objc var vc_separatorInset: UIEdgeInsets {
var result = separatorInset
if #available(iOS 11.0, *) {
result.left -= self.safeAreaInsets.left
result.right -= self.safeAreaInsets.right
}
result.left -= self.safeAreaInsets.left
result.right -= self.safeAreaInsets.right
return result
}

View File

@@ -23,71 +23,15 @@ final class RiotSettings: NSObject {
// MARK: - Constants
private enum UserDefaultsKeys {
static let homeserverUrlString = "homeserverurl"
static let identityServerUrlString = "identityserverurl"
static let enableCrashReport = "enableCrashReport"
static let enableRageShake = "enableRageShake"
static let userInterfaceTheme = "userInterfaceTheme"
static let notificationsShowDecryptedContent = "showDecryptedContent"
static let pinRoomsWithMissedNotifications = "pinRoomsWithMissedNotif"
static let pinRoomsWithUnreadMessages = "pinRoomsWithUnread"
static let allowStunServerFallback = "allowStunServerFallback"
static let hideVerifyThisSessionAlert = "hideVerifyThisSessionAlert"
static let hideReviewSessionsAlert = "hideReviewSessionsAlert"
static let matrixApps = "matrixApps"
static let showNSFWPublicRooms = "showNSFWPublicRooms"
static let settingsScreenShowChangePassword = "settingsScreenShowChangePassword"
static let settingsScreenShowInviteFriends = "settingsScreenShowInviteFriends"
static let settingsScreenShowEnableStunServerFallback = "settingsScreenShowEnableStunServerFallback"
static let settingsSecurityScreenShowSessions = "settingsSecurityScreenShowSessions"
static let settingsSecurityScreenShowSetupBackup = "settingsSecurityScreenShowSetupBackup"
static let settingsSecurityScreenShowRestoreBackup = "settingsSecurityScreenShowRestoreBackup"
static let settingsSecurityScreenShowDeleteBackup = "settingsSecurityScreenShowDeleteBackup"
static let settingsSecurityScreenShowCryptographyInfo = "settingsSecurityScreenShowCryptographyInfo"
static let settingsSecurityScreenShowCryptographyExport = "settingsSecurityScreenShowCryptographyExport"
static let settingsSecurityScreenShowAdvancedUnverifiedDevices = "settingsSecurityScreenShowAdvancedBlacklistUnverifiedDevices"
static let roomCreationScreenAllowEncryptionConfiguration = "roomCreationScreenAllowEncryptionConfiguration"
static let roomCreationScreenRoomIsEncrypted = "roomCreationScreenRoomIsEncrypted"
static let roomCreationScreenAllowRoomTypeConfiguration = "roomCreationScreenAllowRoomTypeConfiguration"
static let roomCreationScreenRoomIsPublic = "roomCreationScreenRoomIsPublic"
static let allowInviteExernalUsers = "allowInviteExernalUsers"
static let enableRingingForGroupCalls = "enableRingingForGroupCalls"
static let roomSettingsScreenShowLowPriorityOption = "roomSettingsScreenShowLowPriorityOption"
static let roomSettingsScreenShowDirectChatOption = "roomSettingsScreenShowDirectChatOption"
static let roomSettingsScreenAllowChangingAccessSettings = "roomSettingsScreenAllowChangingAccessSettings"
static let roomSettingsScreenAllowChangingHistorySettings = "roomSettingsScreenAllowChangingHistorySettings"
static let roomSettingsScreenShowAddressSettings = "roomSettingsScreenShowAddressSettings"
static let roomSettingsScreenShowFlairSettings = "roomSettingsScreenShowFlairSettings"
static let roomSettingsScreenShowAdvancedSettings = "roomSettingsScreenShowAdvancedSettings"
static let roomSettingsScreenAdvancedShowEncryptToVerifiedOption = "roomSettingsScreenAdvancedShowEncryptToVerifiedOption"
static let settingsScreenShowNotificationDecodedContentOption = "settingsScreenShowNotificationDecodedContentOption"
static let settingsScreenShowNsfwRoomsOption = "settingsScreenShowNsfwRoomsOption"
static let roomsAllowToJoinPublicRooms = "roomsAllowToJoinPublicRooms"
static let homeScreenShowFavouritesTab = "homeScreenShowFavouritesTab"
static let homeScreenShowPeopleTab = "homeScreenShowPeopleTab"
static let homeScreenShowRoomsTab = "homeScreenShowRoomsTab"
static let homeScreenShowCommunitiesTab = "homeScreenShowCommunitiesTab"
static let roomScreenAllowVoIPForDirectRoom = "roomScreenAllowVoIPForDirectRoom"
static let roomScreenAllowVoIPForNonDirectRoom = "roomScreenAllowVoIPForNonDirectRoom"
static let roomScreenAllowCameraAction = "roomScreenAllowCameraAction"
static let roomScreenAllowMediaLibraryAction = "roomScreenAllowMediaLibraryAction"
static let roomScreenAllowStickerAction = "roomScreenAllowStickerAction"
static let roomScreenAllowFilesAction = "roomScreenAllowFilesAction"
static let roomContextualMenuShowMoreOptionForMessages = "roomContextualMenuShowMoreOptionForMessages"
static let roomContextualMenuShowMoreOptionForStates = "roomContextualMenuShowMoreOptionForStates"
static let roomContextualMenuShowReportContentOption = "roomContextualMenuShowReportContentOption"
static let roomInfoScreenShowIntegrations = "roomInfoScreenShowIntegrations"
static let roomMemberScreenShowIgnore = "roomMemberScreenShowIgnore"
static let unifiedSearchScreenShowPublicDirectory = "unifiedSearchScreenShowPublicDirectory"
static let hideSpaceBetaAnnounce = "hideSpaceBetaAnnounce"
static let secretsRecoveryAllowReset = "secretsRecoveryAllowReset"
static let versionCheckNextDisplayDateTimeInterval = "versionCheckNextDisplayDateTimeInterval"
}
static let shared = RiotSettings()
/// UserDefaults to be used on reads and writes.
private lazy var defaults: UserDefaults = {
static var defaults: UserDefaults = {
guard let userDefaults = UserDefaults(suiteName: BuildSettings.applicationGroupIdentifier) else {
fatalError("[RiotSettings] Fail to load shared UserDefaults")
}
@@ -98,34 +42,9 @@ final class RiotSettings: NSObject {
super.init()
}
// MARK: Servers
var homeserverUrlString: String {
get {
return defaults.string(forKey: UserDefaultsKeys.homeserverUrlString) ?? BuildSettings.serverConfigDefaultHomeserverUrlString
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.homeserverUrlString)
}
}
var identityServerUrlString: String {
get {
return defaults.string(forKey: UserDefaultsKeys.identityServerUrlString) ?? BuildSettings.serverConfigDefaultIdentityServerUrlString
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.identityServerUrlString)
}
}
// MARK: Notifications
/// Indicate if `showDecryptedContentInNotifications` settings has been set once.
var isShowDecryptedContentInNotificationsHasBeenSetOnce: Bool {
return defaults.object(forKey: UserDefaultsKeys.notificationsShowDecryptedContent) != nil
}
/// Indicate if UserDefaults suite has been migrated once.
var isUserDefaultsMigrated: Bool {
return defaults.object(forKey: UserDefaultsKeys.notificationsShowDecryptedContent) != nil
return RiotSettings.defaults.object(forKey: UserDefaultsKeys.notificationsShowDecryptedContent) != nil
}
func migrate() {
@@ -135,615 +54,247 @@ final class RiotSettings: NSObject {
// write values to suite
// remove redundant values from standard
for (key, value) in dictionary {
defaults.set(value, forKey: key)
RiotSettings.defaults.set(value, forKey: key)
UserDefaults.standard.removeObject(forKey: key)
}
}
/// Indicate if encrypted messages content should be displayed in notifications.
var showDecryptedContentInNotifications: Bool {
get {
return defaults.bool(forKey: UserDefaultsKeys.notificationsShowDecryptedContent)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.notificationsShowDecryptedContent)
}
// MARK: Servers
@UserDefault(key: "homeserverurl", defaultValue: BuildSettings.serverConfigDefaultHomeserverUrlString, storage: defaults)
var homeserverUrlString
@UserDefault(key: "identityserverurl", defaultValue: BuildSettings.serverConfigDefaultIdentityServerUrlString, storage: defaults)
var identityServerUrlString
// MARK: Notifications
/// Indicate if `showDecryptedContentInNotifications` settings has been set once.
var isShowDecryptedContentInNotificationsHasBeenSetOnce: Bool {
return RiotSettings.defaults.object(forKey: UserDefaultsKeys.notificationsShowDecryptedContent) != nil
}
/// Indicate if encrypted messages content should be displayed in notifications.
@UserDefault(key: UserDefaultsKeys.notificationsShowDecryptedContent, defaultValue: false, storage: defaults)
var showDecryptedContentInNotifications
/// Indicate if rooms with missed notifications should be displayed first on home screen.
var pinRoomsWithMissedNotificationsOnHome: Bool {
get {
return defaults.bool(forKey: UserDefaultsKeys.pinRoomsWithMissedNotifications)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.pinRoomsWithMissedNotifications)
}
}
@UserDefault(key: "pinRoomsWithMissedNotif", defaultValue: false, storage: defaults)
var pinRoomsWithMissedNotificationsOnHome
/// Indicate if rooms with unread messages should be displayed first on home screen.
var pinRoomsWithUnreadMessagesOnHome: Bool {
get {
return defaults.bool(forKey: UserDefaultsKeys.pinRoomsWithUnreadMessages)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.pinRoomsWithUnreadMessages)
}
}
@UserDefault(key: "pinRoomsWithUnread", defaultValue: false, storage: defaults)
var pinRoomsWithUnreadMessagesOnHome
/// Indicate to show Not Safe For Work public rooms.
var showNSFWPublicRooms: Bool {
get {
return defaults.bool(forKey: UserDefaultsKeys.showNSFWPublicRooms)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.showNSFWPublicRooms)
}
}
@UserDefault(key: "showNSFWPublicRooms", defaultValue: false, storage: defaults)
var showNSFWPublicRooms
// MARK: User interface
var userInterfaceTheme: String? {
get {
return defaults.string(forKey: UserDefaultsKeys.userInterfaceTheme)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.userInterfaceTheme)
}
}
@UserDefault<String?>(key: "userInterfaceTheme", defaultValue: nil, storage: defaults)
var userInterfaceTheme
// MARK: Other
/// Indicate if `enableCrashReport` settings has been set once.
var isEnableCrashReportHasBeenSetOnce: Bool {
return defaults.object(forKey: UserDefaultsKeys.enableCrashReport) != nil
return RiotSettings.defaults.object(forKey: UserDefaultsKeys.enableCrashReport) != nil
}
var enableCrashReport: Bool {
get {
return defaults.bool(forKey: UserDefaultsKeys.enableCrashReport)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.enableCrashReport)
}
}
@UserDefault(key: UserDefaultsKeys.enableCrashReport, defaultValue: false, storage: defaults)
var enableCrashReport
var enableRageShake: Bool {
get {
return defaults.bool(forKey: UserDefaultsKeys.enableRageShake)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.enableRageShake)
}
}
@UserDefault(key: "enableRageShake", defaultValue: false, storage: defaults)
var enableRageShake
// MARK: Labs
/// Indicates if CallKit ringing is enabled for group calls. This setting does not disable the CallKit integration for group calls, only relates to ringing.
var enableRingingForGroupCalls: Bool {
get {
return defaults.bool(forKey: UserDefaultsKeys.enableRingingForGroupCalls)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.enableRingingForGroupCalls)
}
}
@UserDefault(key: "enableRingingForGroupCalls", defaultValue: false, storage: defaults)
var enableRingingForGroupCalls
// MARK: Calls
/// Indicate if `allowStunServerFallback` settings has been set once.
var isAllowStunServerFallbackHasBeenSetOnce: Bool {
return defaults.object(forKey: UserDefaultsKeys.allowStunServerFallback) != nil
}
var allowStunServerFallback: Bool {
get {
return defaults.bool(forKey: UserDefaultsKeys.allowStunServerFallback)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.allowStunServerFallback)
}
return RiotSettings.defaults.object(forKey: UserDefaultsKeys.allowStunServerFallback) != nil
}
@UserDefault(key: UserDefaultsKeys.allowStunServerFallback, defaultValue: false, storage: defaults)
var allowStunServerFallback
// MARK: Key verification
var hideVerifyThisSessionAlert: Bool {
get {
return defaults.bool(forKey: UserDefaultsKeys.hideVerifyThisSessionAlert)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.hideVerifyThisSessionAlert)
}
}
@UserDefault(key: "hideVerifyThisSessionAlert", defaultValue: false, storage: defaults)
var hideVerifyThisSessionAlert
var hideReviewSessionsAlert: Bool {
get {
return defaults.bool(forKey: UserDefaultsKeys.hideReviewSessionsAlert)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.hideReviewSessionsAlert)
}
}
@UserDefault(key: "hideReviewSessionsAlert", defaultValue: false, storage: defaults)
var hideReviewSessionsAlert
var matrixApps: Bool {
get {
return defaults.bool(forKey: UserDefaultsKeys.matrixApps)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.matrixApps)
}
}
@UserDefault(key: "matrixApps", defaultValue: false, storage: defaults)
var matrixApps
// MARK: - Rooms Screen
var roomsAllowToJoinPublicRooms: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomsAllowToJoinPublicRooms) != nil else {
return BuildSettings.roomsAllowToJoinPublicRooms
}
return defaults.bool(forKey: UserDefaultsKeys.roomsAllowToJoinPublicRooms)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomsAllowToJoinPublicRooms)
}
}
@UserDefault(key: "roomsAllowToJoinPublicRooms", defaultValue: BuildSettings.roomsAllowToJoinPublicRooms, storage: defaults)
var roomsAllowToJoinPublicRooms
// MARK: - Room Screen
var roomScreenAllowVoIPForDirectRoom: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomScreenAllowVoIPForDirectRoom) != nil else {
return BuildSettings.roomScreenAllowVoIPForDirectRoom
}
return defaults.bool(forKey: UserDefaultsKeys.roomScreenAllowVoIPForDirectRoom)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomScreenAllowVoIPForDirectRoom)
}
}
var roomScreenAllowVoIPForNonDirectRoom: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomScreenAllowVoIPForNonDirectRoom) != nil else {
return BuildSettings.roomScreenAllowVoIPForNonDirectRoom
}
return defaults.bool(forKey: UserDefaultsKeys.roomScreenAllowVoIPForNonDirectRoom)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomScreenAllowVoIPForNonDirectRoom)
}
}
var roomScreenAllowCameraAction: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomScreenAllowCameraAction) != nil else {
return BuildSettings.roomScreenAllowCameraAction
}
return defaults.bool(forKey: UserDefaultsKeys.roomScreenAllowCameraAction)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomScreenAllowCameraAction)
}
}
var roomScreenAllowMediaLibraryAction: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomScreenAllowMediaLibraryAction) != nil else {
return BuildSettings.roomScreenAllowMediaLibraryAction
}
return defaults.bool(forKey: UserDefaultsKeys.roomScreenAllowMediaLibraryAction)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomScreenAllowMediaLibraryAction)
}
}
var roomScreenAllowStickerAction: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomScreenAllowStickerAction) != nil else {
return BuildSettings.roomScreenAllowStickerAction
}
return defaults.bool(forKey: UserDefaultsKeys.roomScreenAllowStickerAction)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomScreenAllowStickerAction)
}
}
var roomScreenAllowFilesAction: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomScreenAllowFilesAction) != nil else {
return BuildSettings.roomScreenAllowFilesAction
}
return defaults.bool(forKey: UserDefaultsKeys.roomScreenAllowFilesAction)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomScreenAllowFilesAction)
}
}
@UserDefault(key: "roomScreenAllowVoIPForDirectRoom", defaultValue: BuildSettings.roomScreenAllowVoIPForDirectRoom, storage: defaults)
var roomScreenAllowVoIPForDirectRoom
@UserDefault(key: "roomScreenAllowVoIPForNonDirectRoom", defaultValue: BuildSettings.roomScreenAllowVoIPForNonDirectRoom, storage: defaults)
var roomScreenAllowVoIPForNonDirectRoom
@UserDefault(key: "roomScreenAllowCameraAction", defaultValue: BuildSettings.roomScreenAllowCameraAction, storage: defaults)
var roomScreenAllowCameraAction
@UserDefault(key: "roomScreenAllowMediaLibraryAction", defaultValue: BuildSettings.roomScreenAllowMediaLibraryAction, storage: defaults)
var roomScreenAllowMediaLibraryAction
@UserDefault(key: "roomScreenAllowStickerAction", defaultValue: BuildSettings.roomScreenAllowStickerAction, storage: defaults)
var roomScreenAllowStickerAction
@UserDefault(key: "roomScreenAllowFilesAction", defaultValue: BuildSettings.roomScreenAllowFilesAction, storage: defaults)
var roomScreenAllowFilesAction
// MARK: - Room Contextual Menu
var roomContextualMenuShowMoreOptionForMessages: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomContextualMenuShowMoreOptionForMessages) != nil else {
return BuildSettings.roomContextualMenuShowMoreOptionForMessages
}
return defaults.bool(forKey: UserDefaultsKeys.roomContextualMenuShowMoreOptionForMessages)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomContextualMenuShowMoreOptionForMessages)
}
}
var roomContextualMenuShowMoreOptionForStates: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomContextualMenuShowMoreOptionForStates) != nil else {
return BuildSettings.roomContextualMenuShowMoreOptionForStates
}
return defaults.bool(forKey: UserDefaultsKeys.roomContextualMenuShowMoreOptionForStates)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomContextualMenuShowMoreOptionForStates)
}
}
var roomContextualMenuShowReportContentOption: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomContextualMenuShowReportContentOption) != nil else {
return BuildSettings.roomContextualMenuShowReportContentOption
}
return defaults.bool(forKey: UserDefaultsKeys.roomContextualMenuShowReportContentOption)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomContextualMenuShowReportContentOption)
}
}
@UserDefault(key: "roomContextualMenuShowMoreOptionForMessages", defaultValue: BuildSettings.roomContextualMenuShowMoreOptionForMessages, storage: defaults)
var roomContextualMenuShowMoreOptionForMessages
@UserDefault(key: "roomContextualMenuShowMoreOptionForStates", defaultValue: BuildSettings.roomContextualMenuShowMoreOptionForStates, storage: defaults)
var roomContextualMenuShowMoreOptionForStates
@UserDefault(key: "roomContextualMenuShowReportContentOption", defaultValue: BuildSettings.roomContextualMenuShowReportContentOption, storage: defaults)
var roomContextualMenuShowReportContentOption
// MARK: - Room Info Screen
var roomInfoScreenShowIntegrations: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomInfoScreenShowIntegrations) != nil else {
return BuildSettings.roomInfoScreenShowIntegrations
}
return defaults.bool(forKey: UserDefaultsKeys.roomInfoScreenShowIntegrations)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomInfoScreenShowIntegrations)
}
}
@UserDefault(key: "roomInfoScreenShowIntegrations", defaultValue: BuildSettings.roomInfoScreenShowIntegrations, storage: defaults)
var roomInfoScreenShowIntegrations
// MARK: - Room Member Screen
var roomMemberScreenShowIgnore: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomMemberScreenShowIgnore) != nil else {
return BuildSettings.roomMemberScreenShowIgnore
}
return defaults.bool(forKey: UserDefaultsKeys.roomMemberScreenShowIgnore)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomMemberScreenShowIgnore)
}
}
@UserDefault(key: "roomMemberScreenShowIgnore", defaultValue: BuildSettings.roomMemberScreenShowIgnore, storage: defaults)
var roomMemberScreenShowIgnore
// MARK: - Room Creation Screen
var roomCreationScreenAllowEncryptionConfiguration: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomCreationScreenAllowEncryptionConfiguration) != nil else {
return BuildSettings.roomCreationScreenAllowEncryptionConfiguration
}
return defaults.bool(forKey: UserDefaultsKeys.roomCreationScreenAllowEncryptionConfiguration)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomCreationScreenAllowEncryptionConfiguration)
}
}
var roomCreationScreenRoomIsEncrypted: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomCreationScreenRoomIsEncrypted) != nil else {
return BuildSettings.roomCreationScreenRoomIsEncrypted
}
return defaults.bool(forKey: UserDefaultsKeys.roomCreationScreenRoomIsEncrypted)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomCreationScreenRoomIsEncrypted)
}
}
var roomCreationScreenAllowRoomTypeConfiguration: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomCreationScreenAllowRoomTypeConfiguration) != nil else {
return BuildSettings.roomCreationScreenAllowRoomTypeConfiguration
}
return defaults.bool(forKey: UserDefaultsKeys.roomCreationScreenAllowRoomTypeConfiguration)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomCreationScreenAllowRoomTypeConfiguration)
}
}
var roomCreationScreenRoomIsPublic: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomCreationScreenRoomIsPublic) != nil else {
return BuildSettings.roomCreationScreenRoomIsPublic
}
return defaults.bool(forKey: UserDefaultsKeys.roomCreationScreenRoomIsPublic)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomCreationScreenRoomIsPublic)
}
}
@UserDefault(key: "roomCreationScreenAllowEncryptionConfiguration", defaultValue: BuildSettings.roomCreationScreenAllowEncryptionConfiguration, storage: defaults)
var roomCreationScreenAllowEncryptionConfiguration
@UserDefault(key: "roomCreationScreenRoomIsEncrypted", defaultValue: BuildSettings.roomCreationScreenRoomIsEncrypted, storage: defaults)
var roomCreationScreenRoomIsEncrypted
@UserDefault(key: "roomCreationScreenAllowRoomTypeConfiguration", defaultValue: BuildSettings.roomCreationScreenAllowRoomTypeConfiguration, storage: defaults)
var roomCreationScreenAllowRoomTypeConfiguration
@UserDefault(key: "roomCreationScreenRoomIsPublic", defaultValue: BuildSettings.roomCreationScreenRoomIsPublic, storage: defaults)
var roomCreationScreenRoomIsPublic
// MARK: Features
var allowInviteExernalUsers: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.allowInviteExernalUsers) != nil else {
return BuildSettings.allowInviteExernalUsers
}
return defaults.bool(forKey: UserDefaultsKeys.allowInviteExernalUsers)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.allowInviteExernalUsers)
}
}
@UserDefault(key: "allowInviteExernalUsers", defaultValue: BuildSettings.allowInviteExernalUsers, storage: defaults)
var allowInviteExernalUsers
// MARK: - Main Tabs
var homeScreenShowFavouritesTab: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.homeScreenShowFavouritesTab) != nil else {
return BuildSettings.homeScreenShowFavouritesTab
}
return defaults.bool(forKey: UserDefaultsKeys.homeScreenShowFavouritesTab)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.homeScreenShowFavouritesTab)
}
}
var homeScreenShowPeopleTab: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.homeScreenShowPeopleTab) != nil else {
return BuildSettings.homeScreenShowPeopleTab
}
return defaults.bool(forKey: UserDefaultsKeys.homeScreenShowPeopleTab)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.homeScreenShowPeopleTab)
}
}
var homeScreenShowRoomsTab: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.homeScreenShowRoomsTab) != nil else {
return BuildSettings.homeScreenShowRoomsTab
}
return defaults.bool(forKey: UserDefaultsKeys.homeScreenShowRoomsTab)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.homeScreenShowRoomsTab)
}
}
var homeScreenShowCommunitiesTab: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.homeScreenShowCommunitiesTab) != nil else {
return BuildSettings.homeScreenShowCommunitiesTab
}
return defaults.bool(forKey: UserDefaultsKeys.homeScreenShowCommunitiesTab)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.homeScreenShowCommunitiesTab)
}
}
@UserDefault(key: "homeScreenShowFavouritesTab", defaultValue: BuildSettings.homeScreenShowFavouritesTab, storage: defaults)
var homeScreenShowFavouritesTab
@UserDefault(key: "homeScreenShowPeopleTab", defaultValue: BuildSettings.homeScreenShowPeopleTab, storage: defaults)
var homeScreenShowPeopleTab
@UserDefault(key: "homeScreenShowRoomsTab", defaultValue: BuildSettings.homeScreenShowRoomsTab, storage: defaults)
var homeScreenShowRoomsTab
@UserDefault(key: "homeScreenShowCommunitiesTab", defaultValue: BuildSettings.homeScreenShowCommunitiesTab, storage: defaults)
var homeScreenShowCommunitiesTab
// MARK: General Settings
var settingsScreenShowChangePassword: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.settingsScreenShowChangePassword) != nil else {
return BuildSettings.settingsScreenShowChangePassword
}
return defaults.bool(forKey: UserDefaultsKeys.settingsScreenShowChangePassword)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.settingsScreenShowChangePassword)
}
}
var settingsScreenShowInviteFriends: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.settingsScreenShowInviteFriends) != nil else {
return BuildSettings.settingsScreenShowInviteFriends
}
return defaults.bool(forKey: UserDefaultsKeys.settingsScreenShowInviteFriends)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.settingsScreenShowInviteFriends)
}
}
var settingsScreenShowEnableStunServerFallback: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.settingsScreenShowInviteFriends) != nil else {
return BuildSettings.settingsScreenShowEnableStunServerFallback
}
return defaults.bool(forKey: UserDefaultsKeys.settingsScreenShowEnableStunServerFallback)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.settingsScreenShowEnableStunServerFallback)
}
}
var settingsScreenShowNotificationDecodedContentOption: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.settingsScreenShowNotificationDecodedContentOption) != nil else {
return BuildSettings.settingsScreenShowNotificationDecodedContentOption
}
return defaults.bool(forKey: UserDefaultsKeys.settingsScreenShowNotificationDecodedContentOption)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.settingsScreenShowNotificationDecodedContentOption)
}
}
var settingsScreenShowNsfwRoomsOption: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.settingsScreenShowNsfwRoomsOption) != nil else {
return BuildSettings.settingsScreenShowNsfwRoomsOption
}
return defaults.bool(forKey: UserDefaultsKeys.settingsScreenShowNsfwRoomsOption)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.settingsScreenShowNsfwRoomsOption)
}
}
var settingsSecurityScreenShowSessions: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.settingsSecurityScreenShowSessions) != nil else {
return BuildSettings.settingsSecurityScreenShowSessions
}
return defaults.bool(forKey: UserDefaultsKeys.settingsSecurityScreenShowSessions)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.settingsSecurityScreenShowSessions)
}
}
var settingsSecurityScreenShowSetupBackup: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.settingsSecurityScreenShowSetupBackup) != nil else {
return BuildSettings.settingsSecurityScreenShowSetupBackup
}
return defaults.bool(forKey: UserDefaultsKeys.settingsSecurityScreenShowSetupBackup)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.settingsSecurityScreenShowSetupBackup)
}
}
var settingsSecurityScreenShowRestoreBackup: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.settingsSecurityScreenShowRestoreBackup) != nil else {
return BuildSettings.settingsSecurityScreenShowRestoreBackup
}
return defaults.bool(forKey: UserDefaultsKeys.settingsSecurityScreenShowRestoreBackup)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.settingsSecurityScreenShowRestoreBackup)
}
}
var settingsSecurityScreenShowDeleteBackup: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.settingsSecurityScreenShowDeleteBackup) != nil else {
return BuildSettings.settingsSecurityScreenShowDeleteBackup
}
return defaults.bool(forKey: UserDefaultsKeys.settingsSecurityScreenShowDeleteBackup)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.settingsSecurityScreenShowDeleteBackup)
}
}
var settingsSecurityScreenShowCryptographyInfo: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.settingsSecurityScreenShowCryptographyInfo) != nil else {
return BuildSettings.settingsSecurityScreenShowCryptographyInfo
}
return defaults.bool(forKey: UserDefaultsKeys.settingsSecurityScreenShowCryptographyInfo)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.settingsSecurityScreenShowCryptographyInfo)
}
}
var settingsSecurityScreenShowCryptographyExport: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.settingsSecurityScreenShowCryptographyExport) != nil else {
return BuildSettings.settingsSecurityScreenShowCryptographyExport
}
return defaults.bool(forKey: UserDefaultsKeys.settingsSecurityScreenShowCryptographyExport)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.settingsSecurityScreenShowCryptographyExport)
}
}
var settingsSecurityScreenShowAdvancedUnverifiedDevices: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.settingsSecurityScreenShowAdvancedUnverifiedDevices) != nil else {
return BuildSettings.settingsSecurityScreenShowAdvancedUnverifiedDevices
}
return defaults.bool(forKey: UserDefaultsKeys.settingsSecurityScreenShowAdvancedUnverifiedDevices)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.settingsSecurityScreenShowAdvancedUnverifiedDevices)
}
}
@UserDefault(key: "settingsScreenShowChangePassword", defaultValue: BuildSettings.settingsScreenShowChangePassword, storage: defaults)
var settingsScreenShowChangePassword
@UserDefault(key: "settingsScreenShowInviteFriends", defaultValue: BuildSettings.settingsScreenShowInviteFriends, storage: defaults)
var settingsScreenShowInviteFriends
@UserDefault(key: "settingsScreenShowEnableStunServerFallback", defaultValue: BuildSettings.settingsScreenShowEnableStunServerFallback, storage: defaults)
var settingsScreenShowEnableStunServerFallback
@UserDefault(key: "settingsScreenShowNotificationDecodedContentOption", defaultValue: BuildSettings.settingsScreenShowNotificationDecodedContentOption, storage: defaults)
var settingsScreenShowNotificationDecodedContentOption
@UserDefault(key: "settingsScreenShowNsfwRoomsOption", defaultValue: BuildSettings.settingsScreenShowNsfwRoomsOption, storage: defaults)
var settingsScreenShowNsfwRoomsOption
@UserDefault(key: "settingsSecurityScreenShowSessions", defaultValue: BuildSettings.settingsSecurityScreenShowSessions, storage: defaults)
var settingsSecurityScreenShowSessions
@UserDefault(key: "settingsSecurityScreenShowSetupBackup", defaultValue: BuildSettings.settingsSecurityScreenShowSetupBackup, storage: defaults)
var settingsSecurityScreenShowSetupBackup
@UserDefault(key: "settingsSecurityScreenShowRestoreBackup", defaultValue: BuildSettings.settingsSecurityScreenShowRestoreBackup, storage: defaults)
var settingsSecurityScreenShowRestoreBackup
@UserDefault(key: "settingsSecurityScreenShowDeleteBackup", defaultValue: BuildSettings.settingsSecurityScreenShowDeleteBackup, storage: defaults)
var settingsSecurityScreenShowDeleteBackup
@UserDefault(key: "settingsSecurityScreenShowCryptographyInfo", defaultValue: BuildSettings.settingsSecurityScreenShowCryptographyInfo, storage: defaults)
var settingsSecurityScreenShowCryptographyInfo
@UserDefault(key: "settingsSecurityScreenShowCryptographyExport", defaultValue: BuildSettings.settingsSecurityScreenShowCryptographyExport, storage: defaults)
var settingsSecurityScreenShowCryptographyExport
@UserDefault(key: "settingsSecurityScreenShowAdvancedBlacklistUnverifiedDevices", defaultValue: BuildSettings.settingsSecurityScreenShowAdvancedUnverifiedDevices, storage: defaults)
var settingsSecurityScreenShowAdvancedUnverifiedDevices
// MARK: - Room Settings Screen
var roomSettingsScreenShowLowPriorityOption: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomSettingsScreenShowLowPriorityOption) != nil else {
return BuildSettings.roomSettingsScreenShowLowPriorityOption
}
return defaults.bool(forKey: UserDefaultsKeys.roomSettingsScreenShowLowPriorityOption)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomSettingsScreenShowLowPriorityOption)
}
}
var roomSettingsScreenShowDirectChatOption: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomSettingsScreenShowDirectChatOption) != nil else {
return BuildSettings.roomSettingsScreenShowDirectChatOption
}
return defaults.bool(forKey: UserDefaultsKeys.roomSettingsScreenShowDirectChatOption)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomSettingsScreenShowDirectChatOption)
}
}
var roomSettingsScreenAllowChangingAccessSettings: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomSettingsScreenAllowChangingAccessSettings) != nil else {
return BuildSettings.roomSettingsScreenAllowChangingAccessSettings
}
return defaults.bool(forKey: UserDefaultsKeys.roomSettingsScreenAllowChangingAccessSettings)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomSettingsScreenAllowChangingAccessSettings)
}
}
var roomSettingsScreenAllowChangingHistorySettings: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomSettingsScreenAllowChangingHistorySettings) != nil else {
return BuildSettings.roomSettingsScreenAllowChangingHistorySettings
}
return defaults.bool(forKey: UserDefaultsKeys.roomSettingsScreenAllowChangingHistorySettings)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomSettingsScreenAllowChangingHistorySettings)
}
}
var roomSettingsScreenShowAddressSettings: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomSettingsScreenShowAddressSettings) != nil else {
return BuildSettings.roomSettingsScreenShowAddressSettings
}
return defaults.bool(forKey: UserDefaultsKeys.roomSettingsScreenShowAddressSettings)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomSettingsScreenShowAddressSettings)
}
}
var roomSettingsScreenShowFlairSettings: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomSettingsScreenShowFlairSettings) != nil else {
return BuildSettings.roomSettingsScreenShowFlairSettings
}
return defaults.bool(forKey: UserDefaultsKeys.roomSettingsScreenShowFlairSettings)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomSettingsScreenShowFlairSettings)
}
}
var roomSettingsScreenShowAdvancedSettings: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomSettingsScreenShowAdvancedSettings) != nil else {
return BuildSettings.roomSettingsScreenShowAdvancedSettings
}
return defaults.bool(forKey: UserDefaultsKeys.roomSettingsScreenShowAdvancedSettings)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomSettingsScreenShowAdvancedSettings)
}
}
var roomSettingsScreenAdvancedShowEncryptToVerifiedOption: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.roomSettingsScreenAdvancedShowEncryptToVerifiedOption) != nil else {
return BuildSettings.roomSettingsScreenAdvancedShowEncryptToVerifiedOption
}
return defaults.bool(forKey: UserDefaultsKeys.roomSettingsScreenAdvancedShowEncryptToVerifiedOption)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.roomSettingsScreenAdvancedShowEncryptToVerifiedOption)
}
}
@UserDefault(key: "roomSettingsScreenShowLowPriorityOption", defaultValue: BuildSettings.roomSettingsScreenShowLowPriorityOption, storage: defaults)
var roomSettingsScreenShowLowPriorityOption
@UserDefault(key: "roomSettingsScreenShowDirectChatOption", defaultValue: BuildSettings.roomSettingsScreenShowDirectChatOption, storage: defaults)
var roomSettingsScreenShowDirectChatOption
@UserDefault(key: "roomSettingsScreenAllowChangingAccessSettings", defaultValue: BuildSettings.roomSettingsScreenAllowChangingAccessSettings, storage: defaults)
var roomSettingsScreenAllowChangingAccessSettings
@UserDefault(key: "roomSettingsScreenAllowChangingHistorySettings", defaultValue: BuildSettings.roomSettingsScreenAllowChangingHistorySettings, storage: defaults)
var roomSettingsScreenAllowChangingHistorySettings
@UserDefault(key: "roomSettingsScreenShowAddressSettings", defaultValue: BuildSettings.roomSettingsScreenShowAddressSettings, storage: defaults)
var roomSettingsScreenShowAddressSettings
@UserDefault(key: "roomSettingsScreenShowFlairSettings", defaultValue: BuildSettings.roomSettingsScreenShowFlairSettings, storage: defaults)
var roomSettingsScreenShowFlairSettings
@UserDefault(key: "roomSettingsScreenShowAdvancedSettings", defaultValue: BuildSettings.roomSettingsScreenShowAdvancedSettings, storage: defaults)
var roomSettingsScreenShowAdvancedSettings
@UserDefault(key: "roomSettingsScreenAdvancedShowEncryptToVerifiedOption", defaultValue: BuildSettings.roomSettingsScreenAdvancedShowEncryptToVerifiedOption, storage: defaults)
var roomSettingsScreenAdvancedShowEncryptToVerifiedOption
// MARK: - Unified Search
var unifiedSearchScreenShowPublicDirectory: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.unifiedSearchScreenShowPublicDirectory) != nil else {
return BuildSettings.unifiedSearchScreenShowPublicDirectory
}
return defaults.bool(forKey: UserDefaultsKeys.unifiedSearchScreenShowPublicDirectory)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.unifiedSearchScreenShowPublicDirectory)
}
}
@UserDefault(key: "unifiedSearchScreenShowPublicDirectory", defaultValue: BuildSettings.unifiedSearchScreenShowPublicDirectory, storage: defaults)
var unifiedSearchScreenShowPublicDirectory
// MARK: - Secrets Recovery
var secretsRecoveryAllowReset: Bool {
get {
guard defaults.object(forKey: UserDefaultsKeys.secretsRecoveryAllowReset) != nil else {
return BuildSettings.secretsRecoveryAllowReset
}
return defaults.bool(forKey: UserDefaultsKeys.secretsRecoveryAllowReset)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.secretsRecoveryAllowReset)
}
}
@UserDefault(key: "secretsRecoveryAllowReset", defaultValue: BuildSettings.secretsRecoveryAllowReset, storage: defaults)
var secretsRecoveryAllowReset
// MARK: - Beta
var hideSpaceBetaAnnounce: Bool {
get {
return defaults.bool(forKey: UserDefaultsKeys.hideSpaceBetaAnnounce)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.hideSpaceBetaAnnounce)
}
}
@UserDefault(key: "hideSpaceBetaAnnounce", defaultValue: false, storage: defaults)
var hideSpaceBetaAnnounce
// MARK: - Version check
var versionCheckNextDisplayDateTimeInterval: TimeInterval {
get {
return defaults.double(forKey: UserDefaultsKeys.versionCheckNextDisplayDateTimeInterval)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.versionCheckNextDisplayDateTimeInterval)
}
}
@UserDefault(key: "versionCheckNextDisplayDateTimeInterval", defaultValue: 0.0, storage: defaults)
var versionCheckNextDisplayDateTimeInterval
}

View File

@@ -80,7 +80,6 @@ import DesignKit
var keyboardAppearance: UIKeyboardAppearance { get }
@available(iOS 12.0, *)
var userInterfaceStyle: UIUserInterfaceStyle { get }

View File

@@ -76,7 +76,6 @@ class DarkTheme: NSObject, Theme {
var scrollBarStyle: UIScrollView.IndicatorStyle = .white
var keyboardAppearance: UIKeyboardAppearance = .dark
@available(iOS 12.0, *)
var userInterfaceStyle: UIUserInterfaceStyle {
return .dark
}

View File

@@ -82,7 +82,6 @@ class DefaultTheme: NSObject, Theme {
var scrollBarStyle: UIScrollView.IndicatorStyle = .default
var keyboardAppearance: UIKeyboardAppearance = .light
@available(iOS 12.0, *)
var userInterfaceStyle: UIUserInterfaceStyle {
return .light
}

View File

@@ -708,12 +708,9 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
}
_isAppForeground = YES;
if (@available(iOS 11.0, *))
{
// Riot has its own dark theme. Prevent iOS from applying its one
[application keyWindow].accessibilityIgnoresInvertColors = YES;
}
// Riot has its own dark theme. Prevent iOS from applying its one
[application keyWindow].accessibilityIgnoresInvertColors = YES;
[self handleAppState];
}
@@ -2040,8 +2037,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
if (clearCache)
{
// clear the media cache
[MXMediaManager clearCache];
[self clearCache];
}
}
@@ -2143,7 +2139,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
[self.pushNotificationService deregisterRemoteNotifications];
// Clear cache
[MXMediaManager clearCache];
[self clearCache];
// Reset key backup banner preferences
[SecureBackupBannerPreferences.shared reset];
@@ -4322,4 +4318,13 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
return [authVC continueSSOLoginWithToken:loginToken txnId:txnId];
}
#pragma mark - Private
- (void)clearCache
{
[MXMediaManager clearCache];
[MXKAttachment clearCache];
[VoiceMessageAttachmentCacheManagerBridge clearCache];
}
@end

View File

@@ -1,59 +0,0 @@
//
// Copyright 2020 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
import SafariServices
/// LegacySSOAuthentificationSession is session used to authenticate a user through a web service on iOS 11 and earlier. It uses SFAuthenticationSession.
final class LegacySSOAuthentificationSession: SSOAuthentificationSessionProtocol {
// MARK: - Constants
// MARK: - Properties
private var authentificationSession: SFAuthenticationSession?
// MARK: - Public
func setContextProvider(_ contextProvider: SSOAuthenticationSessionContextProviding) {
}
func authenticate(with url: URL, callbackURLScheme: String?, completionHandler: @escaping SSOAuthenticationSessionCompletionHandler) {
let authentificationSession = SFAuthenticationSession(url: url, callbackURLScheme: callbackURLScheme) { (callbackURL, error) in
var finalError: Error?
if let error = error as? SFAuthenticationError {
switch error.code {
case .canceledLogin:
finalError = SSOAuthentificationSessionError.userCanceled
default:
finalError = error
}
}
completionHandler(callbackURL, finalError)
}
self.authentificationSession = authentificationSession
authentificationSession.start()
}
func cancel() {
self.authentificationSession?.cancel()
}
}

View File

@@ -110,19 +110,11 @@ final class SSOAuthenticationPresenter: NSObject {
return
}
let authenticationSession: SSOAuthentificationSessionProtocol
let authenticationSession = SSOAuthentificationSession()
if #available(iOS 12.0, *) {
authenticationSession = SSOAuthentificationSession()
} else {
authenticationSession = LegacySSOAuthentificationSession()
}
if #available(iOS 12.0, *) {
if let presentingWindow = presentingViewController.view.window {
let contextProvider = SSOAuthenticationSessionContextProvider(window: presentingWindow)
authenticationSession.setContextProvider(contextProvider)
}
if let presentingWindow = presentingViewController.view.window {
let contextProvider = SSOAuthenticationSessionContextProvider(window: presentingWindow)
authenticationSession.setContextProvider(contextProvider)
}
authenticationSession.authenticate(with: authenticationURL, callbackURLScheme: self.ssoAuthenticationService.callBackURLScheme) { [weak self] (callBackURL, error) in

View File

@@ -18,7 +18,6 @@ import Foundation
import AuthenticationServices
/// Provides context to target where in an application's UI the authorization view should be shown.
@available(iOS 12.0, *)
class SSOAuthenticationSessionContextProvider: NSObject, SSOAuthenticationSessionContextProviding, ASWebAuthenticationPresentationContextProviding {
let window: UIWindow
@@ -33,7 +32,6 @@ class SSOAuthenticationSessionContextProvider: NSObject, SSOAuthenticationSessio
/// SSOAuthentificationSession is session used to authenticate a user through a web service on iOS 12+. It uses ASWebAuthenticationSession.
/// More information: https://developer.apple.com/documentation/authenticationservices/authenticating_a_user_through_a_web_service
@available(iOS 12.0, *)
final class SSOAuthentificationSession: SSOAuthentificationSessionProtocol {
// MARK: - Constants

View File

@@ -749,7 +749,7 @@
}
// Look for the lowest section index visible in the bottom sticky headers.
CGFloat maxVisiblePosY = self.recentsTableView.contentOffset.y + self.recentsTableView.frame.size.height - self.recentsTableView.mxk_adjustedContentInset.bottom;
CGFloat maxVisiblePosY = self.recentsTableView.contentOffset.y + self.recentsTableView.frame.size.height - self.recentsTableView.adjustedContentInset.bottom;
UIView *lastDisplayedSectionHeader = displayedSectionHeaders.lastObject;
for (UIView *header in _stickyHeadersBottomContainer.subviews)
@@ -1542,7 +1542,7 @@
{
if (!self.recentsSearchBar.isHidden)
{
if (!self.recentsSearchBar.text.length && (scrollView.contentOffset.y + scrollView.mxk_adjustedContentInset.top > self.recentsSearchBar.frame.size.height))
if (!self.recentsSearchBar.text.length && (scrollView.contentOffset.y + scrollView.adjustedContentInset.top > self.recentsSearchBar.frame.size.height))
{
// Hide the search bar
[self hideSearchBar:YES];
@@ -1991,7 +1991,7 @@
- (void)scrollToTop:(BOOL)animated
{
[self.recentsTableView setContentOffset:CGPointMake(-self.recentsTableView.mxk_adjustedContentInset.left, -self.recentsTableView.mxk_adjustedContentInset.top) animated:animated];
[self.recentsTableView setContentOffset:CGPointMake(-self.recentsTableView.adjustedContentInset.left, -self.recentsTableView.adjustedContentInset.top) animated:animated];
}
- (void)scrollToTheTopTheNextRoomWithMissedNotificationsInSection:(NSInteger)section

View File

@@ -545,7 +545,7 @@
{
if (!self.groupsSearchBar.isHidden)
{
if (!self.groupsSearchBar.text.length && (scrollView.contentOffset.y + scrollView.mxk_adjustedContentInset.top > self.groupsSearchBar.frame.size.height))
if (!self.groupsSearchBar.text.length && (scrollView.contentOffset.y + scrollView.adjustedContentInset.top > self.groupsSearchBar.frame.size.height))
{
// Hide the search bar
[self hideSearchBar:YES];
@@ -590,7 +590,7 @@
- (void)scrollToTop:(BOOL)animated
{
[self.groupsTableView setContentOffset:CGPointMake(-self.groupsTableView.mxk_adjustedContentInset.left, -self.groupsTableView.mxk_adjustedContentInset.top) animated:animated];
[self.groupsTableView setContentOffset:CGPointMake(-self.groupsTableView.adjustedContentInset.left, -self.groupsTableView.adjustedContentInset.top) animated:animated];
}
#pragma mark - MXKGroupListViewControllerDelegate

View File

@@ -167,7 +167,7 @@
// Observe kAppDelegateDidTapStatusBarNotification.
kAppDelegateDidTapStatusBarNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kAppDelegateDidTapStatusBarNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
[self.contactsTableView setContentOffset:CGPointMake(-self.contactsTableView.mxk_adjustedContentInset.left, -self.contactsTableView.mxk_adjustedContentInset.top) animated:YES];
[self.contactsTableView setContentOffset:CGPointMake(-self.contactsTableView.adjustedContentInset.left, -self.contactsTableView.adjustedContentInset.top) animated:YES];
}];
@@ -353,7 +353,7 @@
- (void)scrollToTop:(BOOL)animated
{
// Scroll to the top
[self.contactsTableView setContentOffset:CGPointMake(-self.contactsTableView.mxk_adjustedContentInset.left, -self.contactsTableView.mxk_adjustedContentInset.top) animated:animated];
[self.contactsTableView setContentOffset:CGPointMake(-self.contactsTableView.adjustedContentInset.left, -self.contactsTableView.adjustedContentInset.top) animated:animated];
}
#pragma mark - UITableView delegate

View File

@@ -113,7 +113,7 @@
// Observe kAppDelegateDidTapStatusBarNotificationObserver.
kAppDelegateDidTapStatusBarNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kAppDelegateDidTapStatusBarNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
[self.tableView setContentOffset:CGPointMake(-self.tableView.mxk_adjustedContentInset.left, -self.tableView.mxk_adjustedContentInset.top) animated:YES];
[self.tableView setContentOffset:CGPointMake(-self.tableView.adjustedContentInset.left, -self.tableView.adjustedContentInset.top) animated:YES];
}];
@@ -200,7 +200,7 @@
// Preview the public room
if (publicRoom.worldReadable)
{
RoomPreviewData *roomPreviewData = [[RoomPreviewData alloc] initWithRoomId:publicRoom.roomId andSession:dataSource.mxSession];
RoomPreviewData *roomPreviewData = [[RoomPreviewData alloc] initWithPublicRoom:publicRoom andSession:dataSource.mxSession];
[self startActivityIndicator];

View File

@@ -27,6 +27,8 @@ class HomeViewControllerWithBannerWrapperViewController: UIViewController, Banne
super.init(nibName: nil, bundle: nil)
extendedLayoutIncludesOpaqueBars = true
self.tabBarItem.tag = viewController.tabBarItem.tag
self.tabBarItem.image = viewController.tabBarItem.image
self.accessibilityLabel = viewController.accessibilityLabel

View File

@@ -19,7 +19,7 @@ import Foundation
class VersionCheckCoordinator: Coordinator, VersionCheckBannerViewDelegate, VersionCheckAlertViewControllerDelegate {
private enum Constants {
static let osVersionToBeDropped = 11
static let hasOSVersionBeenDropped = false
static let hasOSVersionBeenDropped = true
static let supportURL = URL(string: "https://support.apple.com/en-gb/guide/iphone/iph3e504502/ios")
}

View File

@@ -36,15 +36,14 @@ final class BubbleReactionActionViewCell: UICollectionViewCell, NibReusable, The
// MARK: - Life cycle
override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
if #available(iOS 12.0, *) {
/*
On iOS 12, there are issues with self-sizing cells as described in Apple release notes (https://developer.apple.com/documentation/ios_release_notes/ios_12_release_notes) :
"You might encounter issues with systemLayoutSizeFitting(_:) when using a UICollectionViewCell subclass that requires updateConstraints().
(42138227) Workaround: Don't call the cell's setNeedsUpdateConstraints() method unless you need to support live constraint changes.
If you need to support live constraint changes, call updateConstraintsIfNeeded() before calling systemLayoutSizeFitting(_:)."
*/
self.updateConstraintsIfNeeded()
}
/*
On iOS 12, there are issues with self-sizing cells as described in Apple release notes (https://developer.apple.com/documentation/ios_release_notes/ios_12_release_notes) :
"You might encounter issues with systemLayoutSizeFitting(_:) when using a UICollectionViewCell subclass that requires updateConstraints().
(42138227) Workaround: Don't call the cell's setNeedsUpdateConstraints() method unless you need to support live constraint changes.
If you need to support live constraint changes, call updateConstraintsIfNeeded() before calling systemLayoutSizeFitting(_:)."
*/
self.updateConstraintsIfNeeded()
return super.preferredLayoutAttributesFitting(layoutAttributes)
}

View File

@@ -57,15 +57,14 @@ final class BubbleReactionViewCell: UICollectionViewCell, NibReusable, Themable
}
override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
if #available(iOS 12.0, *) {
/*
On iOS 12, there are issues with self-sizing cells as described in Apple release notes (https://developer.apple.com/documentation/ios_release_notes/ios_12_release_notes) :
"You might encounter issues with systemLayoutSizeFitting(_:) when using a UICollectionViewCell subclass that requires updateConstraints().
(42138227) Workaround: Don't call the cell's setNeedsUpdateConstraints() method unless you need to support live constraint changes.
If you need to support live constraint changes, call updateConstraintsIfNeeded() before calling systemLayoutSizeFitting(_:)."
*/
self.updateConstraintsIfNeeded()
}
/*
On iOS 12, there are issues with self-sizing cells as described in Apple release notes (https://developer.apple.com/documentation/ios_release_notes/ios_12_release_notes) :
"You might encounter issues with systemLayoutSizeFitting(_:) when using a UICollectionViewCell subclass that requires updateConstraints().
(42138227) Workaround: Don't call the cell's setNeedsUpdateConstraints() method unless you need to support live constraint changes.
If you need to support live constraint changes, call updateConstraintsIfNeeded() before calling systemLayoutSizeFitting(_:)."
*/
self.updateConstraintsIfNeeded()
return super.preferredLayoutAttributesFitting(layoutAttributes)
}

View File

@@ -58,11 +58,7 @@ final class RoomContextualMenuViewController: UIViewController, Themable {
private var hiddenToolbarViewBottomConstant: CGFloat {
let bottomSafeAreaHeight: CGFloat
if #available(iOS 11.0, *) {
bottomSafeAreaHeight = self.view.safeAreaInsets.bottom
} else {
bottomSafeAreaHeight = self.bottomLayoutGuide.length
}
bottomSafeAreaHeight = self.view.safeAreaInsets.bottom
return -(self.menuToolbarViewHeightConstraint.constant + bottomSafeAreaHeight)
}

View File

@@ -92,9 +92,7 @@ final class EmojiPickerViewController: UIViewController {
// Enable to hide search bar on scrolling after first time view appear
// Commenting out below code for now. It broke the navigation bar background. For details: https://github.com/vector-im/riot-ios/issues/3271
// if #available(iOS 11.0, *) {
// self.navigationItem.hidesSearchBarWhenScrolling = true
// }
// self.navigationItem.hidesSearchBarWhenScrolling = true
}
override func viewDidDisappear(_ animated: Bool) {
@@ -140,9 +138,7 @@ final class EmojiPickerViewController: UIViewController {
self.setupCollectionView()
if #available(iOS 11.0, *) {
self.setupSearchController()
}
self.setupSearchController()
}
private func setupCollectionView() {
@@ -158,10 +154,8 @@ final class EmojiPickerViewController: UIViewController {
collectionViewFlowLayout.sectionInset = CollectionViewLayout.sectionInsets
collectionViewFlowLayout.sectionHeadersPinToVisibleBounds = true // Enable sticky headers
// Avoid device notch in landascape (e.g. iPhone X)
if #available(iOS 11.0, *) {
collectionViewFlowLayout.sectionInsetReference = .fromSafeArea
}
// Avoid device notch in landscape (e.g. iPhone X)
collectionViewFlowLayout.sectionInsetReference = .fromSafeArea
}
self.collectionView.register(supplementaryViewType: EmojiPickerHeaderView.self, ofKind: UICollectionView.elementKindSectionHeader)
@@ -175,11 +169,9 @@ final class EmojiPickerViewController: UIViewController {
searchController.searchBar.placeholder = VectorL10n.searchDefaultPlaceholder
searchController.hidesNavigationBarDuringPresentation = false
if #available(iOS 11.0, *) {
self.navigationItem.searchController = searchController
// Make the search bar visible on first view appearance
self.navigationItem.hidesSearchBarWhenScrolling = false
}
self.navigationItem.searchController = searchController
// Make the search bar visible on first view appearance
self.navigationItem.hidesSearchBarWhenScrolling = false
self.definesPresentationContext = true

View File

@@ -562,7 +562,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
// Observe kAppDelegateDidTapStatusBarNotification.
kAppDelegateDidTapStatusBarNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kAppDelegateDidTapStatusBarNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
[self setBubbleTableViewContentOffset:CGPointMake(-self.bubblesTableView.mxk_adjustedContentInset.left, -self.bubblesTableView.mxk_adjustedContentInset.top) animated:YES];
[self setBubbleTableViewContentOffset:CGPointMake(-self.bubblesTableView.adjustedContentInset.left, -self.bubblesTableView.adjustedContentInset.top) animated:YES];
}];
if ([self.roomDataSource.roomId isEqualToString:[LegacyAppDelegate theDelegate].lastNavigatedRoomIdFromPush])
@@ -756,7 +756,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
CGRect frame = previewHeader.bottomBorderView.frame;
self.previewHeaderContainerHeightConstraint.constant = frame.origin.y + frame.size.height;
self.bubblesTableViewTopConstraint.constant = self.previewHeaderContainerHeightConstraint.constant - self.bubblesTableView.mxk_adjustedContentInset.top;
self.bubblesTableViewTopConstraint.constant = self.previewHeaderContainerHeightConstraint.constant - self.bubblesTableView.adjustedContentInset.top;
}
else
{
@@ -2262,7 +2262,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseIn
animations:^{
self.bubblesTableViewTopConstraint.constant = self.previewHeaderContainerHeightConstraint.constant - self.bubblesTableView.mxk_adjustedContentInset.top;
self.bubblesTableViewTopConstraint.constant = self.previewHeaderContainerHeightConstraint.constant - self.bubblesTableView.adjustedContentInset.top;
previewHeader.roomAvatar.alpha = 1;
@@ -4108,7 +4108,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
// Switch back to the live mode when the user scrolls to the bottom of the non live timeline.
if (!self.roomDataSource.isLive && ![self isRoomPreview])
{
CGFloat contentBottomPosY = self.bubblesTableView.contentOffset.y + self.bubblesTableView.frame.size.height - self.bubblesTableView.mxk_adjustedContentInset.bottom;
CGFloat contentBottomPosY = self.bubblesTableView.contentOffset.y + self.bubblesTableView.frame.size.height - self.bubblesTableView.adjustedContentInset.bottom;
if (contentBottomPosY >= self.bubblesTableView.contentSize.height && ![self.roomDataSource.timeline canPaginate:MXTimelineDirectionForwards])
{
[self goBackToLive];
@@ -5092,12 +5092,12 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
if (readMarkerTableViewCell && isAppeared && !self.isBubbleTableViewDisplayInTransition)
{
// Check whether the read marker is visible
CGFloat contentTopPosY = self.bubblesTableView.contentOffset.y + self.bubblesTableView.mxk_adjustedContentInset.top;
CGFloat contentTopPosY = self.bubblesTableView.contentOffset.y + self.bubblesTableView.adjustedContentInset.top;
CGFloat readMarkerViewPosY = readMarkerTableViewCell.frame.origin.y + readMarkerTableViewCell.readMarkerView.frame.origin.y;
if (contentTopPosY <= readMarkerViewPosY)
{
// Compute the max vertical position visible according to contentOffset
CGFloat contentBottomPosY = self.bubblesTableView.contentOffset.y + self.bubblesTableView.frame.size.height - self.bubblesTableView.mxk_adjustedContentInset.bottom;
CGFloat contentBottomPosY = self.bubblesTableView.contentOffset.y + self.bubblesTableView.frame.size.height - self.bubblesTableView.adjustedContentInset.bottom;
if (readMarkerViewPosY <= contentBottomPosY)
{
// Launch animation
@@ -5205,7 +5205,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
// The read marker display is still enabled (see roomDataSource.showReadMarker flag),
// this means the read marker was not been visible yet.
// We show the banner if the marker is located in the top hidden part of the cell.
CGFloat contentTopPosY = self.bubblesTableView.contentOffset.y + self.bubblesTableView.mxk_adjustedContentInset.top;
CGFloat contentTopPosY = self.bubblesTableView.contentOffset.y + self.bubblesTableView.adjustedContentInset.top;
CGFloat readMarkerViewPosY = roomBubbleTableViewCell.frame.origin.y + roomBubbleTableViewCell.readMarkerView.frame.origin.y;
self.jumpToLastUnreadBannerContainer.hidden = (contentTopPosY < readMarkerViewPosY);
}

View File

@@ -116,7 +116,7 @@
// Observe kAppDelegateDidTapStatusBarNotificationObserver.
kAppDelegateDidTapStatusBarNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kAppDelegateDidTapStatusBarNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
[self.searchTableView setContentOffset:CGPointMake(-self.searchTableView.mxk_adjustedContentInset.left, -self.searchTableView.mxk_adjustedContentInset.top) animated:YES];
[self.searchTableView setContentOffset:CGPointMake(-self.searchTableView.adjustedContentInset.left, -self.searchTableView.adjustedContentInset.top) animated:YES];
}];
}

View File

@@ -117,7 +117,7 @@
// Observe kAppDelegateDidTapStatusBarNotificationObserver.
kAppDelegateDidTapStatusBarNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kAppDelegateDidTapStatusBarNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
[self.searchTableView setContentOffset:CGPointMake(-self.searchTableView.mxk_adjustedContentInset.left, -self.searchTableView.mxk_adjustedContentInset.top) animated:YES];
[self.searchTableView setContentOffset:CGPointMake(-self.searchTableView.adjustedContentInset.left, -self.searchTableView.adjustedContentInset.top) animated:YES];
}];
}

View File

@@ -320,7 +320,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti
// Observe appDelegateDidTapStatusBarNotificationObserver.
appDelegateDidTapStatusBarNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kAppDelegateDidTapStatusBarNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
[self.tableView setContentOffset:CGPointMake(-self.tableView.mxk_adjustedContentInset.left, -self.tableView.mxk_adjustedContentInset.top) animated:YES];
[self.tableView setContentOffset:CGPointMake(-self.tableView.adjustedContentInset.left, -self.tableView.adjustedContentInset.top) animated:YES];
}];
}

View File

@@ -134,7 +134,7 @@ const CGFloat kComposerContainerTrailingPadding = 12;
{
[self.attachMediaButton setImage:[UIImage imageNamed:@"upload_icon_dark"] forState:UIControlStateNormal];
}
else if (@available(iOS 12.0, *) && ThemeService.shared.theme.userInterfaceStyle == UIUserInterfaceStyleDark) {
else if (ThemeService.shared.theme.userInterfaceStyle == UIUserInterfaceStyleDark) {
[self.attachMediaButton setImage:[UIImage imageNamed:@"upload_icon_dark"] forState:UIControlStateNormal];
}

View File

@@ -26,6 +26,7 @@ enum VoiceMessageAttachmentCacheManagerError: Error {
case durationError(Error?)
case invalidNumberOfSamples
case samplingError
case cancelled
}
/**
@@ -51,6 +52,12 @@ struct VoiceMessageAttachmentCacheManagerLoadResult {
let samples: [Float]
}
@objc class VoiceMessageAttachmentCacheManagerBridge: NSObject {
@objc static func clearCache() {
VoiceMessageAttachmentCacheManager.sharedManager.clearCache()
}
}
class VoiceMessageAttachmentCacheManager {
private struct Constants {
@@ -67,6 +74,10 @@ class VoiceMessageAttachmentCacheManager {
private let workQueue: DispatchQueue
private let operationQueue: OperationQueue
private var temporaryFilesFolderURL: URL {
return URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true).appendingPathComponent("VoiceMessages")
}
private init() {
workQueue = DispatchQueue(label: "io.element.VoiceMessageAttachmentCacheManager.queue", qos: .userInitiated)
operationQueue = OperationQueue()
@@ -76,16 +87,27 @@ class VoiceMessageAttachmentCacheManager {
func loadAttachment(_ attachment: MXKAttachment, numberOfSamples: Int, completion: @escaping (Result<VoiceMessageAttachmentCacheManagerLoadResult, Error>) -> Void) {
guard attachment.type == MXKAttachmentTypeVoiceMessage else {
completion(Result.failure(VoiceMessageAttachmentCacheManagerError.invalidAttachmentType))
MXLog.error("[VoiceMessageAttachmentCacheManager] Invalid attachment type, ignoring request.")
return
}
guard let identifier = attachment.eventId else {
completion(Result.failure(VoiceMessageAttachmentCacheManagerError.invalidEventId))
MXLog.error("[VoiceMessageAttachmentCacheManager] Invalid event id, ignoring request.")
return
}
guard numberOfSamples > 0 else {
completion(Result.failure(VoiceMessageAttachmentCacheManagerError.invalidNumberOfSamples))
MXLog.error("[VoiceMessageAttachmentCacheManager] Invalid number of samples, ignoring request.")
return
}
do {
try setupTemporaryFilesFolder()
} catch {
completion(Result.failure(VoiceMessageAttachmentCacheManagerError.preparationError(error)))
MXLog.error("[VoiceMessageAttachmentCacheManager] Failed creating temporary files folder with error: \(error)")
return
}
@@ -105,6 +127,23 @@ class VoiceMessageAttachmentCacheManager {
}
}
func clearCache() {
for key in completionCallbacks.keys {
invokeFailureCallbacksForIdentifier(key.eventIdentifier, requiredNumberOfSamples: key.requiredNumberOfSamples, error: VoiceMessageAttachmentCacheManagerError.cancelled)
}
operationQueue.cancelAllOperations()
samples.removeAll()
durations.removeAll()
finalURLs.removeAll()
do {
try FileManager.default.removeItem(at: temporaryFilesFolderURL)
} catch {
MXLog.error("[VoiceMessageAttachmentCacheManager] Failed clearing cached disk files with error: \(error)")
}
}
private func enqueueLoadAttachment(_ attachment: MXKAttachment, identifier: String, numberOfSamples: Int, completion: @escaping (Result<VoiceMessageAttachmentCacheManagerLoadResult, Error>) -> Void) {
let callbackKey = CompletionCallbackKey(eventIdentifier: identifier, requiredNumberOfSamples: numberOfSamples)
@@ -169,8 +208,7 @@ class VoiceMessageAttachmentCacheManager {
return
}
let temporaryDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
let newURL = temporaryDirectoryURL.appendingPathComponent(ProcessInfo().globallyUniqueString).appendingPathExtension("m4a")
let newURL = temporaryFilesFolderURL.appendingPathComponent(ProcessInfo().globallyUniqueString).appendingPathExtension("m4a")
VoiceMessageAudioConverter.convertToMPEG4AAC(sourceURL: URL(fileURLWithPath: filePath), destinationURL: newURL) { result in
self.workQueue.async {
@@ -275,4 +313,9 @@ class VoiceMessageAttachmentCacheManager {
MXLog.debug("[VoiceMessageAttachmentCacheManager] Failed task with error: \(error)")
}
private func setupTemporaryFilesFolder() throws {
let url = temporaryFilesFolderURL
try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil)
}
}

View File

@@ -151,7 +151,7 @@
// Observe kAppDelegateDidTapStatusBarNotificationObserver.
kAppDelegateDidTapStatusBarNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kAppDelegateDidTapStatusBarNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
[self.tableView setContentOffset:CGPointMake(-self.tableView.mxk_adjustedContentInset.left, -self.tableView.mxk_adjustedContentInset.top) animated:YES];
[self.tableView setContentOffset:CGPointMake(-self.tableView.adjustedContentInset.left, -self.tableView.adjustedContentInset.top) animated:YES];
}];

View File

@@ -736,7 +736,7 @@ TableViewSectionsDelegate>
// Observe kAppDelegateDidTapStatusBarNotificationObserver.
kAppDelegateDidTapStatusBarNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kAppDelegateDidTapStatusBarNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
[self.tableView setContentOffset:CGPointMake(-self.tableView.mxk_adjustedContentInset.left, -self.tableView.mxk_adjustedContentInset.top) animated:YES];
[self.tableView setContentOffset:CGPointMake(-self.tableView.adjustedContentInset.left, -self.tableView.adjustedContentInset.top) animated:YES];
}];

View File

@@ -71,11 +71,7 @@ class SlidingModalContainerView: UIView, Themable, NibLoadable {
private var dismissContentViewBottomConstant: CGFloat {
let bottomSafeAreaHeight: CGFloat
if #available(iOS 11.0, *) {
bottomSafeAreaHeight = self.contentView.safeAreaInsets.bottom
} else {
bottomSafeAreaHeight = 0
}
bottomSafeAreaHeight = self.contentView.safeAreaInsets.bottom
return -(self.contentViewHeightConstraint.constant + bottomSafeAreaHeight)
}

View File

@@ -75,8 +75,8 @@
- (HomeViewController *)homeViewController
{
HomeViewControllerWithBannerWrapperViewController *wrapperVC = [self viewControllerForClass:HomeViewControllerWithBannerWrapperViewController.class];
return wrapperVC.homeViewController;
UIViewController *wrapperVC = [self viewControllerForClass:HomeViewControllerWithBannerWrapperViewController.class];
return [(HomeViewControllerWithBannerWrapperViewController *)wrapperVC homeViewController];
}
- (FavouritesViewController *)favouritesViewController

View File

@@ -0,0 +1,61 @@
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Taken from https://www.swiftbysundell.com/articles/property-wrappers-in-swift/
import Foundation
@propertyWrapper
struct UserDefault<Value> {
private let key: String
private let defaultValue: Value
private let storage: UserDefaults
init(key: String, defaultValue: Value, storage: UserDefaults = .standard) {
self.defaultValue = defaultValue
self.key = key
self.storage = storage
}
var wrappedValue: Value {
get {
let value = storage.value(forKey: key) as? Value
return value ?? defaultValue
}
set {
if let optional = newValue as? AnyOptional, optional.isNil {
storage.removeObject(forKey: key)
} else {
storage.setValue(newValue, forKey: key)
}
}
}
}
extension UserDefault where Value: ExpressibleByNilLiteral {
init(key: String, storage: UserDefaults = .standard) {
self.init(key: key, defaultValue: nil, storage: storage)
}
}
private protocol AnyOptional {
var isNil: Bool { get }
}
extension Optional: AnyOptional {
var isNil: Bool { self == nil }
}

View File

@@ -61,3 +61,4 @@ targets:
- path: ../Riot/Categories/String.swift
- path: ../Riot/Categories/Character.swift
- path: ../Riot/Managers/Widgets/WidgetConstants.m
- path: ../Riot/PropertyWrappers/UserDefaultsBackedPropertyWrapper.swift

View File

@@ -267,9 +267,7 @@
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
dispatch_async(dispatch_get_main_queue(), ^{
[self.recentsSearchBar setShowsCancelButton:YES animated:NO];
});
}
@@ -288,7 +286,7 @@
{
if (!self.recentsSearchBar.isHidden)
{
if (!self.recentsSearchBar.text.length && (scrollView.contentOffset.y + scrollView.mxk_adjustedContentInset.top > self.recentsSearchBar.frame.size.height))
if (!self.recentsSearchBar.text.length && (scrollView.contentOffset.y + scrollView.adjustedContentInset.top > self.recentsSearchBar.frame.size.height))
{
// Hide the search bar
[self hideSearchBar:YES];

View File

@@ -56,6 +56,7 @@ targets:
- path: ../Riot/Categories/UISearchBar.swift
- path: ../Riot/Categories/String.swift
- path: ../Riot/Modules/Common/Recents/CellData/RecentCellData.m
- path: ../Riot/PropertyWrappers/UserDefaultsBackedPropertyWrapper.swift
- path: ../Riot/Modules/Common/SegmentedViewController/SegmentedViewController.xib
buildPhase: resources
- path: ../Riot/Assets/en.lproj/Vector.strings

View File

@@ -64,3 +64,4 @@ targets:
- path: ../Riot/Managers/Settings/RiotSettings.swift
- path: ../Riot/Managers/EncryptionKeyManager/EncryptionKeyManager.swift
- path: ../Riot/Managers/KeyValueStorage/
- path: ../Riot/PropertyWrappers/UserDefaultsBackedPropertyWrapper.swift

View File

@@ -48,3 +48,4 @@ targets:
- path: ../Riot/Managers/Settings/RiotSettings.swift
- path: ../Riot/Managers/EncryptionKeyManager/EncryptionKeyManager.swift
- path: ../Riot/Managers/KeyValueStorage
- path: ../Riot/PropertyWrappers/UserDefaultsBackedPropertyWrapper.swift

View File

@@ -1 +0,0 @@
Popping the user back to the home screen after leaving a room.

View File

@@ -1 +0,0 @@
Notifications: Replace "Message" fallback with "Notification" as the event may not be a message.

1
changelog.d/4449.bugfix Normal file
View File

@@ -0,0 +1 @@
Fixed home view being clipped when search is active.

View File

@@ -1 +0,0 @@
Account Notification Settings: Enable/disable notification settings (Default, Mentions & Keywords and Other) and edit Keywords.

View File

@@ -1 +0,0 @@
MXSessionState: Use Swifty versions.

View File

@@ -1 +0,0 @@
Support building Ad-hoc alpha release on pull request (#4635).

View File

@@ -1 +0,0 @@
Notifications: Show the body of all message event types.

View File

@@ -1 +0,0 @@
Notifications: Replies now hide the referenced content.

View File

@@ -1 +0,0 @@
Room Notification Settings: This screen is now implemented in SwiftUI for users on iOS14 or above.

1
changelog.d/4693.build Normal file
View File

@@ -0,0 +1 @@
Bumped the minimum deployment target to iOS 12.1

View File

@@ -1 +0,0 @@
Implemented dialogs to inform users about Element iOS11 deprecation.

View File

@@ -1 +0,0 @@
Fixed flickering voice message cells while being sent.

View File

@@ -1 +0,0 @@
Move app version from AppIdentifiers.xcconfig into a dedicated config file (#4715).

View File

@@ -1 +0,0 @@
Fastfile: Update build number in AppVersion.xcconfig instead of AppIdentifiers.xcconfig.

View File

@@ -1 +0,0 @@
Disabled the create room button while creating a room, preventing duplicates from being created.

View File

@@ -1 +0,0 @@
Fixed cached callbacks race condition, serialized all async operations, properly cleaning up callbacks on failure.

View File

@@ -1 +0,0 @@
Notification Settings: Keywords Notification Setting should be "On" by default.

1
changelog.d/4770.change Normal file
View File

@@ -0,0 +1 @@
Moved converted voice messages to their own folder. Cleaning up all temporary files on on reload and logout.

1
changelog.d/4778.bugfix Normal file
View File

@@ -0,0 +1 @@
DirectoryViewController: Make room preview data to use canonical alias for public rooms.

1
changelog.d/pr-4755.misc Normal file
View File

@@ -0,0 +1 @@
Using a property wrapper for UserDefaults backed application settings (RiotSettings).