mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-28 23:32:41 +00:00
Merge branch 'develop' into doug/4479_media_size_selection
# Conflicts: # Riot/Managers/Settings/RiotSettings.swift
This commit is contained in:
commit
a300cab626
146 changed files with 1741 additions and 1099 deletions
74
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
74
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
name: Bug report for the Element iOS app
|
||||
description: Report any issues that you have found with the Element app. Please [check open issues](https://github.com/vector-im/element-ios/issues) first, in case it has already been reported.
|
||||
labels: [T-Defect]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
|
||||
Please report security issues by email to security@matrix.org
|
||||
- type: textarea
|
||||
id: reproduction-steps
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Please attach screenshots, videos or logs if you can.
|
||||
placeholder: Tell us what you see!
|
||||
value: |
|
||||
1. Where are you starting? What can you see?
|
||||
2. What do you click?
|
||||
3. More steps…
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: result
|
||||
attributes:
|
||||
label: What happened?
|
||||
placeholder: Tell us what went wrong
|
||||
value: |
|
||||
### What did you expect?
|
||||
|
||||
### What happened?
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: device
|
||||
attributes:
|
||||
label: Your phone model
|
||||
placeholder: e.g. iPhoneX
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
id: os
|
||||
attributes:
|
||||
label: Operating system version
|
||||
placeholder: e.g. iOS14.7.1, under "software version"
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Application version
|
||||
description: You can find the version information in Settings -> Help & About.
|
||||
placeholder: e.g. Element version 1.5.2
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
id: homeserver
|
||||
attributes:
|
||||
label: Homeserver
|
||||
description: Which server is your account registered on?
|
||||
placeholder: e.g. matrix.org
|
||||
validations:
|
||||
required: false
|
||||
- type: dropdown
|
||||
id: rageshake
|
||||
attributes:
|
||||
label: Have you submitted a rageshake?
|
||||
description: |
|
||||
Did you know that you can shake your phone to submit logs for this issue? Trigger the defect, then shake your phone and you will see a popup asking if you would like to open the bug report screen. Click YES, and describe the issue, mentioning that you have also filed a bug. Submit the report to send anonymous logs to the developers.
|
||||
options:
|
||||
- 'Yes'
|
||||
- 'No'
|
||||
validations:
|
||||
required: true
|
31
.github/ISSUE_TEMPLATE/bug_report.md
vendored
31
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -1,31 +0,0 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: 'bug'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
#### Describe the bug.
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
#### Steps to reproduce:
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
#### Expected behavior
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
#### Screenshots
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
#### Contextual information:
|
||||
<!-- You can find your device information under Settings -> General -> About -->
|
||||
- Device: <!-- e.g. iPhone6, under "model name"-->
|
||||
- OS: <!-- e.g. iOS8.1, under "software version" -->
|
||||
<!-- The app version should be displayed in the side-panel of the home screen -->
|
||||
- App Version: <!-- e.g. 1.4.5 -->
|
36
.github/ISSUE_TEMPLATE/enhancement.yml
vendored
Normal file
36
.github/ISSUE_TEMPLATE/enhancement.yml
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
name: Enhancement request
|
||||
description: Do you have a suggestion or feature request?
|
||||
labels: [T-Enhancement]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for taking the time to propose a new feature or make a suggestion.
|
||||
- type: textarea
|
||||
id: usecase
|
||||
attributes:
|
||||
label: Your use case
|
||||
description: What would you like to be able to do? Please feel welcome to include screenshots or mock ups.
|
||||
placeholder: Tell us what you would like to do!
|
||||
value: |
|
||||
#### What would you like to do?
|
||||
|
||||
#### Why would you like to do it?
|
||||
|
||||
#### How would you like to achieve it?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: alternative
|
||||
attributes:
|
||||
label: Have you considered any alternatives?
|
||||
placeholder: A clear and concise description of any alternative solutions or features you've considered.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: additional-context
|
||||
attributes:
|
||||
label: Additional context
|
||||
placeholder: Is there anything else you'd like to add?
|
||||
validations:
|
||||
required: false
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
|
@ -1,20 +0,0 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: 'feature'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
#### Is your feature request related to a problem? Please describe.
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
#### Describe the solution you'd like.
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
#### Describe alternatives you've considered.
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
#### Additional context.
|
||||
Add any other context or screenshots about the feature request here.
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -19,6 +19,7 @@ DerivedData
|
|||
out/
|
||||
.vscode/
|
||||
vendor/
|
||||
.DS_Store
|
||||
|
||||
# CocoaPods
|
||||
#
|
||||
|
|
31
CHANGES.md
31
CHANGES.md
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
50
DesignKit/Source/ColorValues.swift
Normal file
50
DesignKit/Source/ColorValues.swift
Normal file
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
/**
|
||||
Struct for holding colour values for a particular theme.
|
||||
*/
|
||||
public struct ColorValues: Colors {
|
||||
|
||||
public let accent: UIColor
|
||||
|
||||
public let alert: UIColor
|
||||
|
||||
public let primaryContent: UIColor
|
||||
|
||||
public let secondaryContent: UIColor
|
||||
|
||||
public let tertiaryContent: UIColor
|
||||
|
||||
public let quarterlyContent: UIColor
|
||||
|
||||
public let quinaryContent: UIColor
|
||||
|
||||
public let separator: UIColor
|
||||
|
||||
public let system: UIColor
|
||||
|
||||
public let tile: UIColor
|
||||
|
||||
public let navigation: UIColor
|
||||
|
||||
public let background: UIColor
|
||||
|
||||
public let namesAndAvatars: [UIColor]
|
||||
}
|
|
@ -15,54 +15,57 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
/// Colors at https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=1255%3A1104
|
||||
@objc public protocol Colors {
|
||||
public protocol Colors {
|
||||
|
||||
associatedtype ColorType
|
||||
|
||||
/// - Focused/Active states
|
||||
/// - CTAs
|
||||
var accent: UIColor { get }
|
||||
var accent: ColorType { get }
|
||||
|
||||
/// - Error messages
|
||||
/// - Content requiring user attention
|
||||
/// - Notification, alerts
|
||||
var alert: UIColor { get }
|
||||
var alert: ColorType { get }
|
||||
|
||||
/// - Text
|
||||
/// - Icons
|
||||
var primaryContent: UIColor { get }
|
||||
var primaryContent: ColorType { get }
|
||||
|
||||
/// - Text
|
||||
/// - Icons
|
||||
var secondaryContent: UIColor { get }
|
||||
var secondaryContent: ColorType { get }
|
||||
|
||||
/// - Text
|
||||
/// - Icons
|
||||
var tertiaryContent: UIColor { get }
|
||||
var tertiaryContent: ColorType { get }
|
||||
|
||||
/// - Text
|
||||
/// - Icons
|
||||
var quarterlyContent: UIColor { get }
|
||||
var quarterlyContent: ColorType { get }
|
||||
|
||||
/// - Text
|
||||
/// - Icons
|
||||
var quinaryContent: UIColor { get }
|
||||
/// - separating lines and other UI components
|
||||
var quinaryContent: ColorType { get }
|
||||
|
||||
/// - System-based areas and backgrounds
|
||||
var system: ColorType { get }
|
||||
|
||||
/// Separating line
|
||||
var separator: UIColor { get }
|
||||
var separator: ColorType { get }
|
||||
|
||||
// Cards, tiles
|
||||
var tile: UIColor { get }
|
||||
var tile: ColorType { get }
|
||||
|
||||
/// Top navigation background on iOS
|
||||
var navigation: UIColor { get }
|
||||
var navigation: ColorType { get }
|
||||
|
||||
/// Background UI color
|
||||
var background: UIColor { get }
|
||||
var background: ColorType { get }
|
||||
|
||||
/// - Names in chat timeline
|
||||
/// - Avatars default states that include first name letter
|
||||
var namesAndAvatars: [UIColor] { get }
|
||||
var namesAndAvatars: [ColorType] { get }
|
||||
|
||||
}
|
||||
|
|
67
DesignKit/Source/ColorsSwiftUI.swift
Normal file
67
DesignKit/Source/ColorsSwiftUI.swift
Normal file
|
@ -0,0 +1,67 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
/**
|
||||
Struct for holding colors for use in SwiftUI.
|
||||
*/
|
||||
@available(iOS 14.0, *)
|
||||
public struct ColorSwiftUI: Colors {
|
||||
|
||||
public let accent: Color
|
||||
|
||||
public let alert: Color
|
||||
|
||||
public let primaryContent: Color
|
||||
|
||||
public let secondaryContent: Color
|
||||
|
||||
public let tertiaryContent: Color
|
||||
|
||||
public let quarterlyContent: Color
|
||||
|
||||
public let quinaryContent: Color
|
||||
|
||||
public let separator: Color
|
||||
|
||||
public var system: Color
|
||||
|
||||
public let tile: Color
|
||||
|
||||
public let navigation: Color
|
||||
|
||||
public let background: Color
|
||||
|
||||
public let namesAndAvatars: [Color]
|
||||
|
||||
init(values: ColorValues) {
|
||||
accent = Color(values.accent)
|
||||
alert = Color(values.alert)
|
||||
primaryContent = Color(values.primaryContent)
|
||||
secondaryContent = Color(values.secondaryContent)
|
||||
tertiaryContent = Color(values.tertiaryContent)
|
||||
quarterlyContent = Color(values.quarterlyContent)
|
||||
quinaryContent = Color(values.quinaryContent)
|
||||
separator = Color(values.separator)
|
||||
system = Color(values.system)
|
||||
tile = Color(values.tile)
|
||||
navigation = Color(values.navigation)
|
||||
background = Color(values.background)
|
||||
namesAndAvatars = values.namesAndAvatars.map({ Color($0) })
|
||||
}
|
||||
}
|
67
DesignKit/Source/ColorsUIkit.swift
Normal file
67
DesignKit/Source/ColorsUIkit.swift
Normal file
|
@ -0,0 +1,67 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
/**
|
||||
ObjC class for holding colors for use in UIKit.
|
||||
*/
|
||||
@objcMembers public class ColorsUIKit: NSObject {
|
||||
|
||||
public let accent: UIColor
|
||||
|
||||
public let alert: UIColor
|
||||
|
||||
public let primaryContent: UIColor
|
||||
|
||||
public let secondaryContent: UIColor
|
||||
|
||||
public let tertiaryContent: UIColor
|
||||
|
||||
public let quarterlyContent: UIColor
|
||||
|
||||
public let quinaryContent: UIColor
|
||||
|
||||
public let separator: UIColor
|
||||
|
||||
public let system: UIColor
|
||||
|
||||
public let tile: UIColor
|
||||
|
||||
public let navigation: UIColor
|
||||
|
||||
public let background: UIColor
|
||||
|
||||
public let namesAndAvatars: [UIColor]
|
||||
|
||||
init(values: ColorValues) {
|
||||
accent = values.accent
|
||||
alert = values.alert
|
||||
primaryContent = values.primaryContent
|
||||
secondaryContent = values.secondaryContent
|
||||
tertiaryContent = values.tertiaryContent
|
||||
quarterlyContent = values.quarterlyContent
|
||||
quinaryContent = values.quinaryContent
|
||||
separator = values.separator
|
||||
system = values.system
|
||||
tile = values.tile
|
||||
navigation = values.navigation
|
||||
background = values.background
|
||||
namesAndAvatars = values.namesAndAvatars
|
||||
}
|
||||
}
|
||||
|
|
@ -19,65 +19,67 @@ import UIKit
|
|||
/// Describe fonts used in the application.
|
||||
/// Font names are based on Element typograhy https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=1362%3A0 which is based on Apple font text styles (UIFont.TextStyle): https://developer.apple.com/documentation/uikit/uifonttextstyle
|
||||
/// Create a custom TextStyle enum (like DesignKit.Fonts.TextStyle) is also a possiblity
|
||||
@objc public protocol Fonts {
|
||||
public protocol Fonts {
|
||||
|
||||
associatedtype FontType
|
||||
|
||||
/// The font for large titles.
|
||||
var largeTitle: UIFont { get }
|
||||
var largeTitle: FontType { get }
|
||||
|
||||
/// `largeTitle` with a Bold weight.
|
||||
var largeTitleB: UIFont { get }
|
||||
var largeTitleB: FontType { get }
|
||||
|
||||
/// The font for first-level hierarchical headings.
|
||||
var title1: UIFont { get }
|
||||
var title1: FontType { get }
|
||||
|
||||
/// `title1` with a Bold weight.
|
||||
var title1B: UIFont { get }
|
||||
var title1B: FontType { get }
|
||||
|
||||
/// The font for second-level hierarchical headings.
|
||||
var title2: UIFont { get }
|
||||
var title2: FontType { get }
|
||||
|
||||
/// `title2` with a Bold weight.
|
||||
var title2B: UIFont { get }
|
||||
var title2B: FontType { get }
|
||||
|
||||
/// The font for third-level hierarchical headings.
|
||||
var title3: UIFont { get }
|
||||
var title3: FontType { get }
|
||||
|
||||
/// `title3` with a Semi Bold weight.
|
||||
var title3SB: UIFont { get }
|
||||
var title3SB: FontType { get }
|
||||
|
||||
/// The font for headings.
|
||||
var headline: UIFont { get }
|
||||
var headline: FontType { get }
|
||||
|
||||
/// The font for subheadings.
|
||||
var subheadline: UIFont { get }
|
||||
var subheadline: FontType { get }
|
||||
|
||||
/// The font for body text.
|
||||
var body: UIFont { get }
|
||||
var body: FontType { get }
|
||||
|
||||
/// `body` with a Semi Bold weight.
|
||||
var bodySB: UIFont { get }
|
||||
var bodySB: FontType { get }
|
||||
|
||||
/// The font for callouts.
|
||||
var callout: UIFont { get }
|
||||
var callout: FontType { get }
|
||||
|
||||
/// `callout` with a Semi Bold weight.
|
||||
var calloutSB: UIFont { get }
|
||||
var calloutSB: FontType { get }
|
||||
|
||||
/// The font for footnotes.
|
||||
var footnote: UIFont { get }
|
||||
var footnote: FontType { get }
|
||||
|
||||
/// `footnote` with a Semi Bold weight.
|
||||
var footnoteSB: UIFont { get }
|
||||
var footnoteSB: FontType { get }
|
||||
|
||||
/// The font for standard captions.
|
||||
var caption1: UIFont { get }
|
||||
var caption1: FontType { get }
|
||||
|
||||
/// `caption1` with a Semi Bold weight.
|
||||
var caption1SB: UIFont { get }
|
||||
var caption1SB: FontType { get }
|
||||
|
||||
/// The font for alternate captions.
|
||||
var caption2: UIFont { get }
|
||||
var caption2: FontType { get }
|
||||
|
||||
/// `caption2` with a Semi Bold weight.
|
||||
var caption2SB: UIFont { get }
|
||||
var caption2SB: FontType { get }
|
||||
}
|
||||
|
|
88
DesignKit/Source/FontsSwiftUI.swift
Normal file
88
DesignKit/Source/FontsSwiftUI.swift
Normal file
|
@ -0,0 +1,88 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
/**
|
||||
Struct for holding fonts for use in SwiftUI.
|
||||
*/
|
||||
@available(iOS 14.0, *)
|
||||
public struct FontSwiftUI: Fonts {
|
||||
public var largeTitle: Font
|
||||
|
||||
public var largeTitleB: Font
|
||||
|
||||
public var title1: Font
|
||||
|
||||
public var title1B: Font
|
||||
|
||||
public var title2: Font
|
||||
|
||||
public var title2B: Font
|
||||
|
||||
public var title3: Font
|
||||
|
||||
public var title3SB: Font
|
||||
|
||||
public var headline: Font
|
||||
|
||||
public var subheadline: Font
|
||||
|
||||
public var body: Font
|
||||
|
||||
public var bodySB: Font
|
||||
|
||||
public var callout: Font
|
||||
|
||||
public var calloutSB: Font
|
||||
|
||||
public var footnote: Font
|
||||
|
||||
public var footnoteSB: Font
|
||||
|
||||
public var caption1: Font
|
||||
|
||||
public var caption1SB: Font
|
||||
|
||||
public var caption2: Font
|
||||
|
||||
public var caption2SB: Font
|
||||
|
||||
public init(values: ElementFonts) {
|
||||
self.largeTitle = Font(values.largeTitle)
|
||||
self.largeTitleB = Font(values.largeTitleB)
|
||||
self.title1 = Font(values.title1)
|
||||
self.title1B = Font(values.title1B)
|
||||
self.title2 = Font(values.title2)
|
||||
self.title2B = Font(values.title2B)
|
||||
self.title3 = Font(values.title3)
|
||||
self.title3SB = Font(values.title3SB)
|
||||
self.headline = Font(values.headline)
|
||||
self.subheadline = Font(values.subheadline)
|
||||
self.body = Font(values.body)
|
||||
self.bodySB = Font(values.bodySB)
|
||||
self.callout = Font(values.callout)
|
||||
self.calloutSB = Font(values.calloutSB)
|
||||
self.footnote = Font(values.footnote)
|
||||
self.footnoteSB = Font(values.footnoteSB)
|
||||
self.caption1 = Font(values.caption1)
|
||||
self.caption1SB = Font(values.caption1SB)
|
||||
self.caption2 = Font(values.caption2)
|
||||
self.caption2SB = Font(values.caption2SB)
|
||||
}
|
||||
}
|
||||
|
87
DesignKit/Source/FontsUIkit.swift
Normal file
87
DesignKit/Source/FontsUIkit.swift
Normal file
|
@ -0,0 +1,87 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
/**
|
||||
ObjC class for holding fonts for use in UIKit.
|
||||
*/
|
||||
@objc public class FontsUIKit: NSObject, Fonts {
|
||||
|
||||
public var largeTitle: UIFont
|
||||
|
||||
public var largeTitleB: UIFont
|
||||
|
||||
public var title1: UIFont
|
||||
|
||||
public var title1B: UIFont
|
||||
|
||||
public var title2: UIFont
|
||||
|
||||
public var title2B: UIFont
|
||||
|
||||
public var title3: UIFont
|
||||
|
||||
public var title3SB: UIFont
|
||||
|
||||
public var headline: UIFont
|
||||
|
||||
public var subheadline: UIFont
|
||||
|
||||
public var body: UIFont
|
||||
|
||||
public var bodySB: UIFont
|
||||
|
||||
public var callout: UIFont
|
||||
|
||||
public var calloutSB: UIFont
|
||||
|
||||
public var footnote: UIFont
|
||||
|
||||
public var footnoteSB: UIFont
|
||||
|
||||
public var caption1: UIFont
|
||||
|
||||
public var caption1SB: UIFont
|
||||
|
||||
public var caption2: UIFont
|
||||
|
||||
public var caption2SB: UIFont
|
||||
|
||||
public init(values: ElementFonts) {
|
||||
self.largeTitle = values.largeTitle
|
||||
self.largeTitleB = values.largeTitleB
|
||||
self.title1 = values.title1
|
||||
self.title1B = values.title1B
|
||||
self.title2 = values.title2
|
||||
self.title2B = values.title2B
|
||||
self.title3 = values.title3
|
||||
self.title3SB = values.title3SB
|
||||
self.headline = values.headline
|
||||
self.subheadline = values.subheadline
|
||||
self.body = values.body
|
||||
self.bodySB = values.bodySB
|
||||
self.callout = values.callout
|
||||
self.calloutSB = values.calloutSB
|
||||
self.footnote = values.footnote
|
||||
self.footnoteSB = values.footnoteSB
|
||||
self.caption1 = values.caption1
|
||||
self.caption1SB = values.caption1SB
|
||||
self.caption2 = values.caption2
|
||||
self.caption2SB = values.caption2SB
|
||||
}
|
||||
}
|
|
@ -21,11 +21,23 @@ import UIKit
|
|||
@objc public protocol ThemeV2 {
|
||||
|
||||
/// Colors object
|
||||
var colors: Colors { get }
|
||||
var colors: ColorsUIKit { get }
|
||||
|
||||
/// Fonts object
|
||||
var fonts: Fonts { get }
|
||||
var fonts: FontsUIKit { get }
|
||||
|
||||
/// may contain more design components in future, like icons, audio files etc.
|
||||
}
|
||||
|
||||
/// Theme v2 for SwiftUI.
|
||||
@available(iOS 14.0, *)
|
||||
public protocol ThemeSwiftUIType {
|
||||
|
||||
/// Colors object
|
||||
var colors: ColorSwiftUI { get }
|
||||
|
||||
/// Fonts object
|
||||
var fonts: FontSwiftUI { get }
|
||||
|
||||
/// may contain more design components in future, like icons, audio files etc.
|
||||
|
||||
}
|
||||
|
|
|
@ -16,43 +16,36 @@
|
|||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
/// Dark theme colors. Will be a struct when things are more Swifty.
|
||||
public class DarkColors: Colors {
|
||||
|
||||
public let accent: UIColor = UIColor(rgb: 0x0DBD8B)
|
||||
|
||||
public let alert: UIColor = UIColor(rgb: 0xFF4B55)
|
||||
|
||||
public let primaryContent: UIColor = UIColor(rgb: 0xFFFFFF)
|
||||
|
||||
public let secondaryContent: UIColor = UIColor(rgb: 0xA9B2BC)
|
||||
|
||||
public let tertiaryContent: UIColor = UIColor(rgb: 0x8E99A4)
|
||||
|
||||
public let quarterlyContent: UIColor = UIColor(rgb: 0x6F7882)
|
||||
|
||||
public let quinaryContent: UIColor = UIColor(rgb: 0x394049)
|
||||
|
||||
public let separator: UIColor = UIColor(rgb: 0x21262C)
|
||||
|
||||
public let tile: UIColor = UIColor(rgb: 0x394049)
|
||||
|
||||
public let navigation: UIColor = UIColor(rgb: 0x21262C)
|
||||
|
||||
public let background: UIColor = UIColor(rgb: 0x15191E)
|
||||
|
||||
public let namesAndAvatars: [UIColor] = [
|
||||
UIColor(rgb: 0x368BD6),
|
||||
UIColor(rgb: 0xAC3BA8),
|
||||
UIColor(rgb: 0x03B381),
|
||||
UIColor(rgb: 0xE64F7A),
|
||||
UIColor(rgb: 0xFF812D),
|
||||
UIColor(rgb: 0x2DC2C5),
|
||||
UIColor(rgb: 0x5C56F5),
|
||||
UIColor(rgb: 0x74D12C)
|
||||
]
|
||||
|
||||
public init() {}
|
||||
/// Dark theme colors.
|
||||
public class DarkColors {
|
||||
private static let values = ColorValues(
|
||||
accent: UIColor(rgb:0x0DBD8B),
|
||||
alert: UIColor(rgb:0xFF4B55),
|
||||
primaryContent: UIColor(rgb:0xFFFFFF),
|
||||
secondaryContent: UIColor(rgb:0xA9B2BC),
|
||||
tertiaryContent: UIColor(rgb:0x8E99A4),
|
||||
quarterlyContent: UIColor(rgb:0x6F7882),
|
||||
quinaryContent: UIColor(rgb:0x394049),
|
||||
separator: UIColor(rgb:0x21262C),
|
||||
system: UIColor(rgb:0x21262C),
|
||||
tile: UIColor(rgb:0x394049),
|
||||
navigation: UIColor(rgb:0x21262C),
|
||||
background: UIColor(rgb:0x15191E),
|
||||
namesAndAvatars: [
|
||||
UIColor(rgb:0x368BD6),
|
||||
UIColor(rgb:0xAC3BA8),
|
||||
UIColor(rgb:0x03B381),
|
||||
UIColor(rgb:0xE64F7A),
|
||||
UIColor(rgb:0xFF812D),
|
||||
UIColor(rgb:0x2DC2C5),
|
||||
UIColor(rgb:0x5C56F5),
|
||||
UIColor(rgb:0x74D12C)
|
||||
]
|
||||
)
|
||||
|
||||
public static var uiKit = ColorsUIKit(values: values)
|
||||
@available(iOS 14.0, *)
|
||||
public static var swiftUI = ColorSwiftUI(values: values)
|
||||
}
|
||||
|
|
|
@ -16,43 +16,42 @@
|
|||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
/// Light theme colors. Will be a struct when things are more Swifty.
|
||||
public class LightColors: Colors {
|
||||
|
||||
public let accent: UIColor = UIColor(rgb: 0x0DBD8B)
|
||||
|
||||
public let alert: UIColor = UIColor(rgb: 0xFF4B55)
|
||||
|
||||
public let primaryContent: UIColor = UIColor(rgb: 0x17191C)
|
||||
|
||||
public let secondaryContent: UIColor = UIColor(rgb: 0x737D8C)
|
||||
|
||||
public let tertiaryContent: UIColor = UIColor(rgb: 0x8D97A5)
|
||||
|
||||
public let quarterlyContent: UIColor = UIColor(rgb: 0xC1C6CD)
|
||||
|
||||
public let quinaryContent: UIColor = UIColor(rgb: 0xE3E8F0)
|
||||
|
||||
public let separator: UIColor = UIColor(rgb: 0xE3E8F0)
|
||||
|
||||
public let tile: UIColor = UIColor(rgb: 0xF3F8FD)
|
||||
|
||||
public let navigation: UIColor = UIColor(rgb: 0xF4F6FA)
|
||||
|
||||
public let background: UIColor = UIColor(rgb: 0xFFFFFF)
|
||||
|
||||
public let namesAndAvatars: [UIColor] = [
|
||||
UIColor(rgb: 0x368BD6),
|
||||
UIColor(rgb: 0xAC3BA8),
|
||||
UIColor(rgb: 0x03B381),
|
||||
UIColor(rgb: 0xE64F7A),
|
||||
UIColor(rgb: 0xFF812D),
|
||||
UIColor(rgb: 0x2DC2C5),
|
||||
UIColor(rgb: 0x5C56F5),
|
||||
UIColor(rgb: 0x74D12C)
|
||||
]
|
||||
|
||||
public init() {}
|
||||
/// Light theme colors.
|
||||
public class LightColors {
|
||||
private static let values = ColorValues(
|
||||
accent: UIColor(rgb:0x0DBD8B),
|
||||
alert: UIColor(rgb:0xFF4B55),
|
||||
primaryContent: UIColor(rgb:0x17191C),
|
||||
secondaryContent: UIColor(rgb:0x737D8C),
|
||||
tertiaryContent: UIColor(rgb:0x8D97A5),
|
||||
quarterlyContent: UIColor(rgb:0xC1C6CD),
|
||||
quinaryContent: UIColor(rgb:0xE3E8F0),
|
||||
separator: UIColor(rgb:0xE3E8F0),
|
||||
system: UIColor(rgb:0xF4F6FA),
|
||||
tile: UIColor(rgb:0xF3F8FD),
|
||||
navigation: UIColor(rgb:0xF4F6FA),
|
||||
background: UIColor(rgb:0xFFFFFF),
|
||||
namesAndAvatars: [
|
||||
UIColor(rgb:0x368BD6),
|
||||
UIColor(rgb:0xAC3BA8),
|
||||
UIColor(rgb:0x03B381),
|
||||
UIColor(rgb:0xE64F7A),
|
||||
UIColor(rgb:0xFF812D),
|
||||
UIColor(rgb:0x2DC2C5),
|
||||
UIColor(rgb:0x5C56F5),
|
||||
UIColor(rgb:0x74D12C)
|
||||
]
|
||||
)
|
||||
|
||||
public static var uiKit = ColorsUIKit(values: values)
|
||||
@available(iOS 14.0, *)
|
||||
public static var swiftUI = ColorSwiftUI(values: values)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
10
Podfile
10
Podfile
|
@ -1,3 +1,5 @@
|
|||
source 'https://cdn.cocoapods.org/'
|
||||
|
||||
# Uncomment this line to define a global platform for your project
|
||||
platform :ios, '11.0'
|
||||
|
||||
|
@ -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'}
|
||||
|
||||
|
@ -46,7 +48,7 @@ abstract_target 'RiotPods' do
|
|||
pod 'GBDeviceInfo', '~> 6.6.0'
|
||||
pod 'Reusable', '~> 4.1'
|
||||
pod 'KeychainAccess', '~> 4.2.2'
|
||||
|
||||
|
||||
# Piwik for analytics
|
||||
pod 'MatomoTracker', '~> 7.4.1'
|
||||
|
||||
|
@ -103,7 +105,7 @@ post_install do |installer|
|
|||
# Plus the app does not enable it
|
||||
config.build_settings['ENABLE_BITCODE'] = 'NO'
|
||||
|
||||
# Make fastlane(xcodebuild) happy by preventing it from building for arm64 simulator
|
||||
# Make fastlane(xcodebuild) happy by preventing it from building for arm64 simulator
|
||||
config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
|
||||
|
||||
# Force ReadMoreTextView to use Swift 5.2 version (as there is no code changes to perform)
|
||||
|
@ -111,7 +113,7 @@ post_install do |installer|
|
|||
config.build_settings['SWIFT_VERSION'] = '5.2'
|
||||
end
|
||||
|
||||
# Stop Xcode 12 complaining about old IPHONEOS_DEPLOYMENT_TARGET from pods
|
||||
# Stop Xcode 12 complaining about old IPHONEOS_DEPLOYMENT_TARGET from pods
|
||||
config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET'
|
||||
end
|
||||
end
|
||||
|
|
32
Podfile.lock
32
Podfile.lock
|
@ -37,7 +37,7 @@ PODS:
|
|||
- DTFoundation/Core
|
||||
- DTFoundation/UIKit (1.7.18):
|
||||
- DTFoundation/Core
|
||||
- ffmpeg-kit-ios-audio (4.4)
|
||||
- ffmpeg-kit-ios-audio (4.4.LTS)
|
||||
- FLEX (4.4.1)
|
||||
- FlowCommoniOS (1.10.0)
|
||||
- GBDeviceInfo (6.6.0):
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -189,7 +189,7 @@ SPEC CHECKSUMS:
|
|||
DSWaveformImage: 3c718a0cf99291887ee70d1d0c18d80101d3d9ce
|
||||
DTCoreText: ec749e013f2e1f76de5e7c7634642e600a7467ce
|
||||
DTFoundation: a53f8cda2489208cbc71c648be177f902ee17536
|
||||
ffmpeg-kit-ios-audio: ddfc3dac6f574e83d53f8ae33586711162685d3e
|
||||
ffmpeg-kit-ios-audio: 1c365080b8c76aa77b87c926f9f66ac07859b342
|
||||
FLEX: 7ca2c8cd3a435ff501ff6d2f2141e9bdc934eaab
|
||||
FlowCommoniOS: bcdf81a5f30717e711af08a8c812eb045411ba94
|
||||
GBDeviceInfo: ed0db16230d2fa280e1cbb39a5a7f60f6946aaec
|
||||
|
@ -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: 7a2c462b09e09029983e15c0e4ad8dcf4d68df69
|
||||
|
||||
COCOAPODS: 1.10.1
|
||||
COCOAPODS: 1.10.2
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
runPostActionsOnFailure = "NO">
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
|
|
|
@ -5155,12 +5155,10 @@ extension VectorL10n {
|
|||
static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String {
|
||||
let format = NSLocalizedString(key, tableName: table, bundle: Bundle(for: BundleToken.self), comment: "")
|
||||
let locale: Locale
|
||||
if let localeIdentifier = Bundle.mxk_language() {
|
||||
locale = Locale(identifier: localeIdentifier)
|
||||
} else if let fallbackLocaleIdentifier = Bundle.mxk_fallbackLanguage() {
|
||||
locale = Locale(identifier: fallbackLocaleIdentifier)
|
||||
if let providedLocale = LocaleProvider.locale {
|
||||
locale = providedLocale
|
||||
} else {
|
||||
locale = Locale.current
|
||||
locale = Locale.current
|
||||
}
|
||||
|
||||
return String(format: format, locale: locale, arguments: args)
|
||||
|
|
31
Riot/Managers/Locale/LocaleProvider.swift
Normal file
31
Riot/Managers/Locale/LocaleProvider.swift
Normal file
|
@ -0,0 +1,31 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Provides the locale logic for Riot app based on mx languages.
|
||||
*/
|
||||
class LocaleProvider: LocaleProviderType {
|
||||
static var locale: Locale? {
|
||||
if let localeIdentifier = Bundle.mxk_language() {
|
||||
return Locale(identifier: localeIdentifier)
|
||||
} else if let fallbackLocaleIdentifier = Bundle.mxk_fallbackLanguage() {
|
||||
return Locale(identifier: fallbackLocaleIdentifier)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
24
Riot/Managers/Locale/LocaleProviderType.swift
Normal file
24
Riot/Managers/Locale/LocaleProviderType.swift
Normal file
|
@ -0,0 +1,24 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Used to provide an application/target specific locale.
|
||||
*/
|
||||
protocol LocaleProviderType {
|
||||
static var locale: Locale? { get }
|
||||
}
|
|
@ -23,72 +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 showMediaCompressionPrompt = "showMediaCompressionPrompt"
|
||||
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")
|
||||
}
|
||||
|
@ -102,34 +45,9 @@ final class RiotSettings: NSObject {
|
|||
])
|
||||
}
|
||||
|
||||
// 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() {
|
||||
|
@ -139,321 +57,151 @@ 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
|
||||
|
||||
/// When set to false the original image is sent and a 1080p preset is used for videos.
|
||||
/// If `BuildSettings.roomInputToolbarCompressionMode` has a value other than prompt, the build setting takes priority for images.
|
||||
|
@ -467,296 +215,99 @@ final class RiotSettings: NSObject {
|
|||
|
||||
// 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
|
||||
}
|
||||
|
|
|
@ -142,12 +142,8 @@ class DarkTheme: NSObject, Theme {
|
|||
}
|
||||
|
||||
/// MARK: - Theme v2
|
||||
var colors: ColorsUIKit = DarkColors.uiKit
|
||||
|
||||
lazy var colors: Colors = {
|
||||
return DarkColors()
|
||||
}()
|
||||
var fonts: FontsUIKit = FontsUIKit(values: ElementFonts())
|
||||
|
||||
lazy var fonts: Fonts = {
|
||||
return ElementFonts()
|
||||
}()
|
||||
}
|
||||
|
|
|
@ -149,12 +149,7 @@ class DefaultTheme: NSObject, Theme {
|
|||
}
|
||||
|
||||
/// MARK: - Theme v2
|
||||
var colors: ColorsUIKit = LightColors.uiKit
|
||||
|
||||
lazy var colors: Colors = {
|
||||
return LightColors()
|
||||
}()
|
||||
|
||||
lazy var fonts: Fonts = {
|
||||
return ElementFonts()
|
||||
}()
|
||||
var fonts: FontsUIKit = FontsUIKit(values: ElementFonts())
|
||||
}
|
||||
|
|
|
@ -103,6 +103,18 @@ final class AppCoordinator: NSObject, AppCoordinatorType {
|
|||
|
||||
private func setupTheme() {
|
||||
ThemeService.shared().themeId = RiotSettings.shared.userInterfaceTheme
|
||||
if #available(iOS 14.0, *) {
|
||||
guard let themeId = ThemeService.shared().themeIdentifier else {
|
||||
MXLog.error("[AppCoordinator] No theme id found to update ThemePublisher")
|
||||
return
|
||||
}
|
||||
ThemePublisher.configure(themeId: themeId)
|
||||
let themeIdPublisher = NotificationCenter.default.publisher(for: Notification.Name.themeServiceDidChangeTheme)
|
||||
.compactMap({ _ in ThemeService.shared().themeIdentifier })
|
||||
.eraseToAnyPublisher()
|
||||
|
||||
ThemePublisher.shared.republish(themeIdPublisher: themeIdPublisher)
|
||||
}
|
||||
}
|
||||
|
||||
private func showAuthentication() {
|
||||
|
|
|
@ -2040,8 +2040,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
|||
|
||||
if (clearCache)
|
||||
{
|
||||
// clear the media cache
|
||||
[MXMediaManager clearCache];
|
||||
[self clearCache];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2143,7 +2142,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
|||
[self.pushNotificationService deregisterRemoteNotifications];
|
||||
|
||||
// Clear cache
|
||||
[MXMediaManager clearCache];
|
||||
[self clearCache];
|
||||
|
||||
// Reset key backup banner preferences
|
||||
[SecureBackupBannerPreferences.shared reset];
|
||||
|
@ -4322,4 +4321,13 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
|||
return [authVC continueSSOLoginWithToken:loginToken txnId:txnId];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)clearCache
|
||||
{
|
||||
[MXMediaManager clearCache];
|
||||
[MXKAttachment clearCache];
|
||||
[VoiceMessageAttachmentCacheManagerBridge clearCache];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -19,14 +19,6 @@ import MatrixSDK
|
|||
import Combine
|
||||
import DesignKit
|
||||
|
||||
/**
|
||||
Provides a simple api to retrieve and cache avatar images
|
||||
*/
|
||||
protocol AvatarServiceType {
|
||||
@available(iOS 14.0, *)
|
||||
func avatarImage(mxContentUri: String, avatarSize: AvatarSize) -> Future<UIImage, Error>
|
||||
}
|
||||
|
||||
enum AvatarServiceError: Error {
|
||||
case pathNotfound
|
||||
case loadingImageFailed(Error?)
|
|
@ -17,7 +17,7 @@
|
|||
import Foundation
|
||||
|
||||
/// AvatarViewDataProtocol describe a view data that should be given to an AvatarView sublcass
|
||||
protocol AvatarViewDataProtocol {
|
||||
protocol AvatarViewDataProtocol: AvatarType {
|
||||
/// Matrix item identifier (user id or room id)
|
||||
var matrixItemId: String { get }
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@ final class RoomNotificationSettingsViewController: UIViewController {
|
|||
activityPresenter.removeCurrentActivityIndicator(animated: true)
|
||||
}
|
||||
self.viewState = viewState
|
||||
if case let .uiKit(avatarData) = viewState.avatarData {
|
||||
if let avatarData = viewState.avatarData as? AvatarViewDataProtocol {
|
||||
mainTableView.tableHeaderView = avatarView
|
||||
avatarView.configure(viewData: avatarData)
|
||||
avatarView.update(theme: theme)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }
|
||||
}
|
|
@ -51,6 +51,10 @@ targets:
|
|||
script: "\"${PODS_ROOT}/SwiftGen/bin/swiftgen\" config run --config \"Tools/SwiftGen/swiftgen-config.yml\"\n"
|
||||
|
||||
sources:
|
||||
- path: ../RiotSwiftUI/Modules
|
||||
# Riot will provide it's own LocaleProviderType so exclude.
|
||||
excludes:
|
||||
- "Common/Locale/LocaleProvider.swift"
|
||||
- path: ../Tools
|
||||
excludes:
|
||||
- "Logs"
|
||||
|
|
|
@ -48,6 +48,8 @@ targets:
|
|||
- path: ../Riot/Modules/SetPinCode/SetupBiometrics/BiometricsAuthenticationPresenter.swift
|
||||
- path: ../Riot/Categories/UNUserNotificationCenter.swift
|
||||
- path: ../Riot/Managers/KeyValueStorage/KeyValueStore.swift
|
||||
- path: ../Riot/Managers/Locale/LocaleProvider.swift
|
||||
- path: ../Riot/Managers/Locale/LocaleProviderType.swift
|
||||
- path: ../Riot/Managers/EncryptionKeyManager/EncryptionKeyManager.swift
|
||||
- path: ../Riot/Categories/Bundle.swift
|
||||
- path: ../Riot/Generated/Strings.swift
|
||||
|
@ -59,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
|
||||
|
|
|
@ -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
|
||||
|
|
28
RiotSwiftUI/Common.xcconfig
Normal file
28
RiotSwiftUI/Common.xcconfig
Normal file
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// Copyright 2021 Vector Creations Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
// Configuration settings file format documentation can be found at:
|
||||
// https://help.apple.com/xcode/#/dev745c5c974
|
||||
|
||||
#include "Config/AppIdentifiers.xcconfig"
|
||||
#include "Config/AppVersion.xcconfig"
|
||||
|
||||
PRODUCT_NAME = RiotSwiftUI
|
||||
PRODUCT_BUNDLE_IDENTIFIER = $(BASE_BUNDLE_IDENTIFIER).riotswiftui
|
||||
|
||||
INFOPLIST_FILE = RiotSwiftUI/Info.plist
|
||||
|
||||
SKIP_INSTALL = YES
|
20
RiotSwiftUI/Debug.xcconfig
Normal file
20
RiotSwiftUI/Debug.xcconfig
Normal file
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// Copyright 2021 Vector Creations Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
// Configuration settings file format documentation can be found at:
|
||||
// https://help.apple.com/xcode/#/dev745c5c974
|
||||
|
||||
#include "Common.xcconfig"
|
22
RiotSwiftUI/Info.plist
Normal file
22
RiotSwiftUI/Info.plist
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -17,6 +17,7 @@
|
|||
import Foundation
|
||||
import Combine
|
||||
import DesignKit
|
||||
import UIKit
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
class MockAvatarService: AvatarServiceType {
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
protocol AvatarInputType {
|
||||
protocol AvatarInputType: AvatarType {
|
||||
var mxContentUri: String? { get }
|
||||
var matrixItemId: String { get }
|
||||
var displayName: String? { get }
|
||||
|
@ -27,8 +27,3 @@ struct AvatarInput: AvatarInputType {
|
|||
var matrixItemId: String
|
||||
let displayName: String?
|
||||
}
|
||||
|
||||
enum AvatarInputOption {
|
||||
case swiftUI(AvatarInputType)
|
||||
case uiKit(AvatarViewDataProtocol)
|
||||
}
|
19
RiotSwiftUI/Modules/Common/Avatar/Model/AvatarType.swift
Normal file
19
RiotSwiftUI/Modules/Common/Avatar/Model/AvatarType.swift
Normal file
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol AvatarType { }
|
|
@ -20,7 +20,7 @@ import DesignKit
|
|||
@available(iOS 14.0, *)
|
||||
struct AvatarImage: View {
|
||||
|
||||
@Environment(\.theme) var theme: Theme
|
||||
@Environment(\.theme) var theme: ThemeSwiftUI
|
||||
@Environment(\.dependencies) var dependencies: DependencyContainer
|
||||
@StateObject var viewModel = AvatarViewModel()
|
||||
|
||||
|
@ -39,7 +39,7 @@ struct AvatarImage: View {
|
|||
.padding(4)
|
||||
.frame(width: CGFloat(size.rawValue), height: CGFloat(size.rawValue))
|
||||
.foregroundColor(.white)
|
||||
.background(Color(theme.avatarColors[colorIndex]))
|
||||
.background(theme.colors.namesAndAvatars[colorIndex])
|
||||
.clipShape(Circle())
|
||||
// Make the text resizable (i.e. Make it large and then allow it to scale down)
|
||||
.font(.system(size: 200))
|
||||
|
@ -57,7 +57,7 @@ struct AvatarImage: View {
|
|||
mxContentUri: mxContentUri,
|
||||
matrixItemId: matrixItemId,
|
||||
displayName: displayName,
|
||||
colorCount: theme.avatarColors.count,
|
||||
colorCount: theme.colors.namesAndAvatars.count,
|
||||
avatarSize: size
|
||||
)
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import DesignKit
|
||||
import Combine
|
||||
import UIKit
|
||||
|
||||
/**
|
||||
Provides a simple api to retrieve and cache avatar images
|
||||
*/
|
||||
protocol AvatarServiceType {
|
||||
@available(iOS 14.0, *)
|
||||
func avatarImage(mxContentUri: String, avatarSize: AvatarSize) -> Future<UIImage, Error>
|
||||
}
|
|
@ -47,7 +47,7 @@ class AvatarViewModel: InjectableObject, ObservableObject {
|
|||
avatarService.avatarImage(mxContentUri: mxContentUri, avatarSize: avatarSize)
|
||||
.sink { completion in
|
||||
guard case let .failure(error) = completion else { return }
|
||||
MXLog.error("[AvatarService] Failed to retrieve avatar: \(error)")
|
||||
// MXLog.error("[AvatarService] Failed to retrieve avatar: \(error)")
|
||||
// TODO: Report non-fatal error when we have Sentry or similar.
|
||||
} receiveValue: { image in
|
||||
self.viewState = .avatar(image)
|
|
@ -15,6 +15,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
enum AvatarViewState {
|
||||
case empty
|
|
@ -23,17 +23,17 @@ import SwiftUI
|
|||
@available(iOS 14.0, *)
|
||||
struct VectorContentModifier: ViewModifier {
|
||||
|
||||
@StateObject private var themeObserver = ThemeObserver.shared
|
||||
@ObservedObject private var themePublisher = ThemePublisher.shared
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.theme(themeObserver.theme)
|
||||
.theme(themePublisher.theme)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
extension View {
|
||||
func vectorContent() -> some View {
|
||||
self.modifier(VectorContentModifier())
|
||||
}
|
||||
func vectorContent() -> some View {
|
||||
self.modifier(VectorContentModifier())
|
||||
}
|
||||
}
|
23
RiotSwiftUI/Modules/Common/Locale/LocaleProvider.swift
Normal file
23
RiotSwiftUI/Modules/Common/Locale/LocaleProvider.swift
Normal file
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class LocaleProvider: LocaleProviderType {
|
||||
static var locale: Locale? {
|
||||
return nil
|
||||
}
|
||||
}
|
|
@ -15,17 +15,21 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
import DesignKit
|
||||
|
||||
/**
|
||||
Extension to `ThemeIdentifier` for getting the SwiftUI theme.
|
||||
*/
|
||||
@available(iOS 14.0, *)
|
||||
class ThemeObserver: ObservableObject {
|
||||
|
||||
static let shared = ThemeObserver()
|
||||
|
||||
init() {
|
||||
NotificationCenter.default.publisher(for: NSNotification.Name.themeServiceDidChangeTheme).map { _ in
|
||||
ThemeService.shared().theme
|
||||
}.assign(to: &$theme)
|
||||
extension ThemeIdentifier {
|
||||
fileprivate static let defaultTheme = DefaultThemeSwiftUI()
|
||||
fileprivate static let darkTheme = DarkThemeSwiftUI()
|
||||
public var themeSwiftUI: ThemeSwiftUI {
|
||||
switch self {
|
||||
case .light:
|
||||
return Self.defaultTheme
|
||||
case .dark, .black:
|
||||
return Self.darkTheme
|
||||
}
|
||||
}
|
||||
@Published var theme: Theme = ThemeService.shared().theme
|
||||
}
|
|
@ -16,14 +16,16 @@
|
|||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import DesignKit
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
private struct ThemeKey: EnvironmentKey {
|
||||
static let defaultValue = ThemeService.shared().theme
|
||||
static let defaultValue = ThemePublisher.shared.theme
|
||||
}
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
extension EnvironmentValues {
|
||||
var theme: Theme {
|
||||
var theme: ThemeSwiftUI {
|
||||
get { self[ThemeKey.self] }
|
||||
set { self[ThemeKey.self] = newValue }
|
||||
}
|
||||
|
@ -36,7 +38,7 @@ extension EnvironmentValues {
|
|||
*/
|
||||
@available(iOS 14.0, *)
|
||||
extension View {
|
||||
func theme(_ theme: Theme) -> some View {
|
||||
func theme(_ theme: ThemeSwiftUI) -> some View {
|
||||
environment(\.theme, theme)
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +51,6 @@ extension View {
|
|||
@available(iOS 14.0, *)
|
||||
extension View {
|
||||
func theme(_ themeId: ThemeIdentifier) -> some View {
|
||||
let theme = ThemeService.shared().theme(withThemeId: themeId.rawValue)
|
||||
return environment(\.theme, theme)
|
||||
return environment(\.theme, themeId.themeSwiftUI)
|
||||
}
|
||||
}
|
51
RiotSwiftUI/Modules/Common/Theme/ThemePublisher.swift
Normal file
51
RiotSwiftUI/Modules/Common/Theme/ThemePublisher.swift
Normal file
|
@ -0,0 +1,51 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
|
||||
/**
|
||||
Provides the theme and theme updates to SwiftUI.
|
||||
Replaces the old ThemeObserver. Riot app can push updates to this class
|
||||
removing the dependency of this class on the `ThemeService`.
|
||||
*/
|
||||
@available(iOS 14.0, *)
|
||||
class ThemePublisher: ObservableObject {
|
||||
|
||||
private static var _shared: ThemePublisher? = nil
|
||||
static var shared: ThemePublisher {
|
||||
if _shared == nil {
|
||||
configure(themeId: .light)
|
||||
}
|
||||
return _shared!
|
||||
}
|
||||
|
||||
@Published private(set) var theme: ThemeSwiftUI
|
||||
|
||||
static func configure(themeId: ThemeIdentifier) {
|
||||
_shared = ThemePublisher(themeId: .light)
|
||||
}
|
||||
|
||||
init(themeId: ThemeIdentifier) {
|
||||
_theme = Published.init(initialValue: themeId.themeSwiftUI)
|
||||
}
|
||||
|
||||
func republish(themeIdPublisher: AnyPublisher<ThemeIdentifier, Never>) {
|
||||
themeIdPublisher
|
||||
.map(\.themeSwiftUI)
|
||||
.assign(to: &$theme)
|
||||
}
|
||||
}
|
23
RiotSwiftUI/Modules/Common/Theme/ThemeSwiftUI.swift
Normal file
23
RiotSwiftUI/Modules/Common/Theme/ThemeSwiftUI.swift
Normal file
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import DesignKit
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
protocol ThemeSwiftUI: ThemeSwiftUIType {
|
||||
var identifier: ThemeIdentifier { get }
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import DesignKit
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
struct DarkThemeSwiftUI: ThemeSwiftUI {
|
||||
var identifier: ThemeIdentifier = .dark
|
||||
var colors: ColorSwiftUI = DarkColors.swiftUI
|
||||
var fonts: FontSwiftUI = FontSwiftUI(values: ElementFonts())
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import DesignKit
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
struct DefaultThemeSwiftUI: ThemeSwiftUI {
|
||||
var identifier: ThemeIdentifier = .light
|
||||
var colors: ColorSwiftUI = LightColors.swiftUI
|
||||
var fonts: FontSwiftUI = FontSwiftUI(values: ElementFonts())
|
||||
}
|
|
@ -38,25 +38,24 @@ final class RoomNotificationSettingsCoordinator: RoomNotificationSettingsCoordin
|
|||
// MARK: - Setup
|
||||
|
||||
init(room: MXRoom, presentedModally: Bool = true) {
|
||||
let roomNotificationService = RoomNotificationSettingsService(room: room)
|
||||
let avatarData: AvatarInputOption?
|
||||
let roomNotificationService = MXRoomNotificationSettingsService(room: room)
|
||||
let avatarData: AvatarType?
|
||||
let showAvatar = presentedModally
|
||||
if #available(iOS 14.0.0, *) {
|
||||
avatarData = showAvatar ? .swiftUI(AvatarInput(
|
||||
avatarData = showAvatar ? AvatarInput(
|
||||
mxContentUri: room.summary.avatar,
|
||||
matrixItemId: room.roomId,
|
||||
displayName: room.summary.displayname
|
||||
)) : nil
|
||||
) : nil
|
||||
} else {
|
||||
avatarData = showAvatar ? .uiKit(RoomAvatarViewData(
|
||||
avatarData = showAvatar ? RoomAvatarViewData(
|
||||
roomId: room.roomId,
|
||||
displayName: room.summary.displayname,
|
||||
avatarUrl: room.summary.avatar,
|
||||
mediaManager: room.mxSession.mediaManager
|
||||
)) : nil
|
||||
) : nil
|
||||
}
|
||||
|
||||
|
||||
let viewModel: RoomNotificationSettingsViewModel
|
||||
let viewController: UIViewController
|
||||
if #available(iOS 14.0.0, *) {
|
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// RoomNotificationSettingsViewController view state
|
||||
struct RoomNotificationSettingsViewState: RoomNotificationSettingsViewStateType {
|
||||
let roomEncrypted: Bool
|
||||
var saving: Bool
|
||||
var notificationState: RoomNotificationState
|
||||
var avatarData: AvatarType?
|
||||
var displayName: String?
|
||||
}
|
||||
|
||||
extension RoomNotificationSettingsViewState {
|
||||
var notificationOptions: [RoomNotificationState] {
|
||||
if roomEncrypted {
|
||||
return [.all, .mute]
|
||||
} else {
|
||||
return RoomNotificationState.allCases
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension RoomNotificationSettingsViewState {
|
||||
var roomEncryptedString: String {
|
||||
roomEncrypted ? VectorL10n.roomNotifsSettingsEncryptedRoomNotice : ""
|
||||
}
|
||||
}
|
||||
|
|
@ -18,36 +18,12 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/// RoomNotificationSettingsViewController view state
|
||||
struct RoomNotificationSettingsViewState: RoomNotificationSettingsViewStateType {
|
||||
let roomEncrypted: Bool
|
||||
var saving: Bool
|
||||
var notificationState: RoomNotificationState
|
||||
var avatarData: AvatarInputOption?
|
||||
var displayName: String?
|
||||
}
|
||||
|
||||
extension RoomNotificationSettingsViewState {
|
||||
var notificationOptions: [RoomNotificationState] {
|
||||
if roomEncrypted {
|
||||
return [.all, .mute]
|
||||
} else {
|
||||
return RoomNotificationState.allCases
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protocol RoomNotificationSettingsViewStateType {
|
||||
var saving: Bool { get }
|
||||
var roomEncrypted: Bool { get }
|
||||
var notificationOptions: [RoomNotificationState] { get }
|
||||
var notificationState: RoomNotificationState { get }
|
||||
var avatarData: AvatarInputOption? { get }
|
||||
var avatarData: AvatarType? { get }
|
||||
var displayName: String? { get }
|
||||
}
|
||||
|
||||
extension RoomNotificationSettingsViewState {
|
||||
var roomEncryptedString: String {
|
||||
roomEncrypted ? VectorL10n.roomNotifsSettingsEncryptedRoomNotice : ""
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
final class RoomNotificationSettingsService: RoomNotificationSettingsServiceType {
|
||||
final class MXRoomNotificationSettingsService: RoomNotificationSettingsServiceType {
|
||||
|
||||
typealias Completion = () -> Void
|
||||
|
|
@ -19,11 +19,11 @@ import SwiftUI
|
|||
|
||||
@available(iOS 14.0, *)
|
||||
struct FormItemButtonStyle: ButtonStyle {
|
||||
@Environment(\.theme) var theme: Theme
|
||||
@Environment(\.theme) var theme: ThemeSwiftUI
|
||||
func makeBody(configuration: Self.Configuration) -> some View {
|
||||
configuration.label
|
||||
.background(configuration.isPressed ? Color(theme.selectedBackgroundColor) : Color(theme.backgroundColor))
|
||||
.foregroundColor(Color(theme.textPrimaryColor))
|
||||
.font(Font(theme.fonts.body))
|
||||
.background(configuration.isPressed ? theme.colors.system : theme.colors.background)
|
||||
.foregroundColor(theme.colors.primaryContent)
|
||||
.font(theme.fonts.body)
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ struct FormPickerItem: View {
|
|||
|
||||
typealias TapCallback = () -> Void
|
||||
|
||||
@Environment(\.theme) var theme: Theme
|
||||
@Environment(\.theme) var theme: ThemeSwiftUI
|
||||
|
||||
var title: String
|
||||
var selected: Bool
|
||||
|
@ -38,7 +38,7 @@ struct FormPickerItem: View {
|
|||
Spacer()
|
||||
if selected {
|
||||
Image("checkmark")
|
||||
.foregroundColor(Color(theme.tintColor))
|
||||
.foregroundColor(theme.colors.accent)
|
||||
}
|
||||
}
|
||||
.padding(.trailing)
|
||||
|
@ -55,6 +55,7 @@ struct FormPickerItem: View {
|
|||
|
||||
@available(iOS 14.0, *)
|
||||
struct FormPickerItem_Previews: PreviewProvider {
|
||||
|
||||
static let items = ["Item 1", "Item 2", "Item 3"]
|
||||
static var selected: String = items[0]
|
||||
static var previews: some View {
|
|
@ -19,16 +19,16 @@ import SwiftUI
|
|||
@available(iOS 14.0, *)
|
||||
struct FormSectionFooter: View {
|
||||
|
||||
@Environment(\.theme) var theme: Theme
|
||||
@Environment(\.theme) var theme: ThemeSwiftUI
|
||||
var text: String
|
||||
|
||||
var body: some View {
|
||||
Text(text)
|
||||
.foregroundColor(Color(theme.textSecondaryColor))
|
||||
.foregroundColor(theme.colors.secondaryContent)
|
||||
.padding(.top)
|
||||
.padding(.leading)
|
||||
.padding(.trailing)
|
||||
.font(Font(theme.fonts.callout))
|
||||
.font(theme.fonts.callout)
|
||||
}
|
||||
}
|
||||
|
|
@ -19,16 +19,16 @@ import SwiftUI
|
|||
@available(iOS 14.0, *)
|
||||
struct FormSectionHeader: View {
|
||||
|
||||
@Environment(\.theme) var theme: Theme
|
||||
@Environment(\.theme) var theme: ThemeSwiftUI
|
||||
var text: String
|
||||
|
||||
var body: some View {
|
||||
Text(text)
|
||||
.foregroundColor(Color(theme.textSecondaryColor))
|
||||
.foregroundColor(theme.colors.secondaryContent)
|
||||
.padding(.top, 32)
|
||||
.padding(.leading)
|
||||
.padding(.bottom, 8)
|
||||
.font(Font(theme.fonts.subheadline))
|
||||
.font(theme.fonts.subheadline)
|
||||
.textCase(.uppercase)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
|
@ -41,7 +41,7 @@ struct RoomNotificationSettings: View {
|
|||
|
||||
var body: some View {
|
||||
VectorForm {
|
||||
if case let .swiftUI(avatarData) = viewModel.viewState.avatarData {
|
||||
if let avatarData = viewModel.viewState.avatarData as? AvatarInputType {
|
||||
RoomNotificationSettingsHeader(
|
||||
avatarData: avatarData,
|
||||
displayName: viewModel.viewState.displayName
|
||||
|
@ -75,7 +75,7 @@ struct RoomNotificationSettings_Previews: PreviewProvider {
|
|||
|
||||
static let mockViewModel = RoomNotificationSettingsSwiftUIViewModel(
|
||||
roomNotificationService: MockRoomNotificationSettingsService.example,
|
||||
avatarData: .swiftUI(MockAvatarInput.example),
|
||||
avatarData: MockAvatarInput.example,
|
||||
displayName: MockAvatarInput.example.displayName,
|
||||
roomEncrypted: true
|
||||
)
|
|
@ -19,7 +19,7 @@ import SwiftUI
|
|||
@available(iOS 14.0, *)
|
||||
struct RoomNotificationSettingsHeader: View {
|
||||
|
||||
@Environment(\.theme) var theme: Theme
|
||||
@Environment(\.theme) var theme: ThemeSwiftUI
|
||||
var avatarData: AvatarInputType
|
||||
var displayName: String?
|
||||
|
||||
|
@ -30,8 +30,8 @@ struct RoomNotificationSettingsHeader: View {
|
|||
AvatarImage(avatarData: avatarData, size: .xxLarge)
|
||||
if let displayName = displayName {
|
||||
Text(displayName)
|
||||
.font(Font(theme.fonts.title3SB))
|
||||
.foregroundColor(Color(theme.textPrimaryColor))
|
||||
.font(theme.fonts.title3SB)
|
||||
.foregroundColor(theme.colors.primaryContent)
|
||||
.textCase(nil)
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@ import SwiftUI
|
|||
@available(iOS 14.0, *)
|
||||
struct VectorForm<Content: View>: View {
|
||||
|
||||
@Environment(\.theme) var theme: Theme
|
||||
@Environment(\.theme) var theme: ThemeSwiftUI
|
||||
var content: () -> Content
|
||||
|
||||
init(@ViewBuilder content: @escaping () -> Content) {
|
||||
|
@ -37,7 +37,7 @@ struct VectorForm<Content: View>: View {
|
|||
maxHeight: .infinity,
|
||||
alignment: .top
|
||||
)
|
||||
.background(Color(theme.baseColor))
|
||||
.background(theme.colors.system)
|
||||
.edgesIgnoringSafeArea(.bottom)
|
||||
|
||||
}
|
|
@ -55,7 +55,7 @@ class RoomNotificationSettingsViewModel: RoomNotificationSettingsViewModelType {
|
|||
|
||||
convenience init(
|
||||
roomNotificationService: RoomNotificationSettingsServiceType,
|
||||
avatarData: AvatarInputOption?,
|
||||
avatarData: AvatarType?,
|
||||
displayName: String?,
|
||||
roomEncrypted: Bool
|
||||
) {
|
|
@ -41,7 +41,7 @@ final class NotificationSettingsCoordinator: NotificationSettingsCoordinatorType
|
|||
|
||||
init(session: MXSession, screen: NotificationSettingsScreen) {
|
||||
self.session = session
|
||||
let notificationSettingsService = NotificationSettingsService(session: session)
|
||||
let notificationSettingsService = MXNotificationSettingsService(session: session)
|
||||
let viewModel = NotificationSettingsViewModel(notificationSettingsService: notificationSettingsService, ruleIds: screen.pushRules)
|
||||
let viewController: UIViewController
|
||||
switch screen {
|
|
@ -0,0 +1,86 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import DesignKit
|
||||
|
||||
/**
|
||||
Conformance of MXPushRule to the abstraction `NotificationPushRule` for use in `NotificationSettingsViewModel`.
|
||||
*/
|
||||
extension MXPushRule: NotificationPushRuleType {
|
||||
|
||||
/*
|
||||
Given a rule, check it match the actions in the static definition.
|
||||
*/
|
||||
func matches(standardActions: NotificationStandardActions?) -> Bool {
|
||||
guard let standardActions = standardActions else {
|
||||
return false
|
||||
}
|
||||
if !enabled && standardActions == .disabled {
|
||||
return true
|
||||
}
|
||||
|
||||
if enabled,
|
||||
let actions = standardActions.actions,
|
||||
highlight == actions.highlight,
|
||||
sound == actions.sound,
|
||||
notify == actions.notify,
|
||||
dontNotify == !actions.notify {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private func getAction(actionType: MXPushRuleActionType, tweakType: String? = nil) -> MXPushRuleAction? {
|
||||
guard let actions = actions as? [MXPushRuleAction] else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return actions.first { action in
|
||||
var match = action.actionType == actionType
|
||||
if let tweakType = tweakType,
|
||||
let actionTweak = action.parameters?["set_tweak"] as? String {
|
||||
match = match && (tweakType == actionTweak)
|
||||
}
|
||||
return match
|
||||
}
|
||||
}
|
||||
|
||||
var highlight: Bool {
|
||||
guard let action = getAction(actionType: MXPushRuleActionTypeSetTweak, tweakType: "highlight") else {
|
||||
return false
|
||||
}
|
||||
if let highlight = action.parameters["value"] as? Bool {
|
||||
return highlight
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
var sound: String? {
|
||||
guard let action = getAction(actionType: MXPushRuleActionTypeSetTweak, tweakType: "sound") else {
|
||||
return nil
|
||||
}
|
||||
return action.parameters["value"] as? String
|
||||
}
|
||||
|
||||
var notify: Bool {
|
||||
return getAction(actionType: MXPushRuleActionTypeNotify) != nil
|
||||
}
|
||||
|
||||
var dontNotify: Bool {
|
||||
return getAction(actionType: MXPushRuleActionTypeDontNotify) != nil
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct MockNotificationPushRule: NotificationPushRuleType {
|
||||
var ruleId: String!
|
||||
var enabled: Bool
|
||||
func matches(standardActions: NotificationStandardActions?) -> Bool {
|
||||
return false
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol NotificationPushRuleType {
|
||||
var ruleId: String! { get }
|
||||
var enabled: Bool { get }
|
||||
func matches(standardActions: NotificationStandardActions?) -> Bool
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue