Settings about section (#1041)

* Fixes #1011 - Add legal information screen in settings, move all settings related screens under Source/Screen/Settings
* Fix warnings after sliding sync api change
This commit is contained in:
Stefan Ceriu
2023-06-07 17:04:42 +03:00
committed by GitHub
parent c0611b4e6b
commit 8ff5c6144c
27 changed files with 408 additions and 123 deletions
+19 -1
View File
@@ -80,6 +80,8 @@ public enum L10n {
public static var actionNotNow: String { return L10n.tr("Localizable", "action_not_now") }
/// OK
public static var actionOk: String { return L10n.tr("Localizable", "action_ok") }
/// Open with
public static var actionOpenWith: String { return L10n.tr("Localizable", "action_open_with") }
/// Quick reply
public static var actionQuickReply: String { return L10n.tr("Localizable", "action_quick_reply") }
/// Quote
@@ -124,12 +126,16 @@ public enum L10n {
public static var actionYes: String { return L10n.tr("Localizable", "action_yes") }
/// About
public static var commonAbout: String { return L10n.tr("Localizable", "common_about") }
/// Acceptable use policy
public static var commonAcceptableUsePolicy: String { return L10n.tr("Localizable", "common_acceptable_use_policy") }
/// Analytics
public static var commonAnalytics: String { return L10n.tr("Localizable", "common_analytics") }
/// Audio
public static var commonAudio: String { return L10n.tr("Localizable", "common_audio") }
/// Bubbles
public static var commonBubbles: String { return L10n.tr("Localizable", "common_bubbles") }
/// Copyright
public static var commonCopyright: String { return L10n.tr("Localizable", "common_copyright") }
/// Creating room…
public static var commonCreatingRoom: String { return L10n.tr("Localizable", "common_creating_room") }
/// Left room
@@ -186,6 +192,8 @@ public enum L10n {
public static var commonPeople: String { return L10n.tr("Localizable", "common_people") }
/// Permalink
public static var commonPermalink: String { return L10n.tr("Localizable", "common_permalink") }
/// Privacy policy
public static var commonPrivacyPolicy: String { return L10n.tr("Localizable", "common_privacy_policy") }
/// Reactions
public static var commonReactions: String { return L10n.tr("Localizable", "common_reactions") }
/// Replying to %1$@
@@ -224,6 +232,8 @@ public enum L10n {
public static var commonSuccess: String { return L10n.tr("Localizable", "common_success") }
/// Suggestions
public static var commonSuggestions: String { return L10n.tr("Localizable", "common_suggestions") }
/// Third-party notices
public static var commonThirdPartyNotices: String { return L10n.tr("Localizable", "common_third_party_notices") }
/// Topic
public static var commonTopic: String { return L10n.tr("Localizable", "common_topic") }
/// What is this room about?
@@ -428,6 +438,14 @@ public enum L10n {
public static var screenAccountProviderChange: String { return L10n.tr("Localizable", "screen_account_provider_change") }
/// Continue
public static var screenAccountProviderContinue: String { return L10n.tr("Localizable", "screen_account_provider_continue") }
/// Homeserver address
public static var screenAccountProviderFormHint: String { return L10n.tr("Localizable", "screen_account_provider_form_hint") }
/// Enter a search term or a domain address.
public static var screenAccountProviderFormNotice: String { return L10n.tr("Localizable", "screen_account_provider_form_notice") }
/// Search for a company, community, or private server.
public static var screenAccountProviderFormSubtitle: String { return L10n.tr("Localizable", "screen_account_provider_form_subtitle") }
/// Find an account provider
public static var screenAccountProviderFormTitle: String { return L10n.tr("Localizable", "screen_account_provider_form_title") }
/// You’re about to sign in to %@
public static func screenAccountProviderSigninTitle(_ p1: Any) -> String {
return L10n.tr("Localizable", "screen_account_provider_signin_title", String(describing: p1))
@@ -608,7 +626,7 @@ public enum L10n {
public static var screenOnboardingSignUp: String { return L10n.tr("Localizable", "screen_onboarding_sign_up") }
/// Communicate and collaborate securely
public static var screenOnboardingSubtitle: String { return L10n.tr("Localizable", "screen_onboarding_subtitle") }
/// Welcome to the %1$@ Beta. Supercharged, for speed and simplicity.
/// Welcome to %1$@. Supercharged, for speed and simplicity.
public static func screenOnboardingWelcomeSubtitle(_ p1: Any) -> String {
return L10n.tr("Localizable", "screen_onboarding_welcome_subtitle", String(describing: p1))
}
@@ -0,0 +1,26 @@
//
// Copyright 2022 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 Combine
import SwiftUI
final class LegalInformationScreenCoordinator: CoordinatorProtocol {
private let viewModel = LegalInformationScreenViewModel()
func toPresentable() -> AnyView {
AnyView(LegalInformationScreen(context: viewModel.context))
}
}
@@ -0,0 +1,23 @@
//
// Copyright 2022 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
enum LegalInformationScreenViewModelAction { }
struct LegalInformationScreenViewState: BindableState { }
enum LegalInformationScreenViewAction { }
@@ -0,0 +1,26 @@
//
// Copyright 2022 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 Combine
import SwiftUI
typealias LegalInformationScreenViewModelType = StateStoreViewModel<LegalInformationScreenViewState, LegalInformationScreenViewAction>
class LegalInformationScreenViewModel: LegalInformationScreenViewModelType, LegalInformationScreenViewModelProtocol {
init() {
super.init(initialViewState: LegalInformationScreenViewState())
}
}
@@ -0,0 +1,22 @@
//
// Copyright 2022 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 Combine
@MainActor
protocol LegalInformationScreenViewModelProtocol {
var context: LegalInformationScreenViewModelType.Context { get }
}
@@ -0,0 +1,52 @@
//
// Copyright 2022 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 SwiftUI
struct LegalInformationScreen: View {
@ObservedObject var context: LegalInformationScreenViewModel.Context
@Environment(\.openURL) private var openURL
var body: some View {
Form {
Section {
Button(L10n.commonCopyright) {
openURL(URL(staticString: "https://element.io/copyright"))
}
Button(L10n.commonAcceptableUsePolicy) {
openURL(URL(staticString: "https://element.io/acceptable-use-policy-terms"))
}
Button(L10n.commonPrivacyPolicy) {
openURL(URL(staticString: "https://element.io/privacy"))
}
}
.buttonStyle(.compoundForm(accessory: .navigationLink))
.compoundFormSection()
}
.compoundForm()
.navigationTitle(L10n.commonAbout)
.navigationBarTitleDisplayMode(.inline)
}
}
// MARK: - Previews
struct LegalInformationScreen_Previews: PreviewProvider {
static let viewModel = LegalInformationScreenViewModel()
static var previews: some View {
LegalInformationScreen(context: viewModel.context)
}
}
@@ -51,6 +51,8 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {
self.presentAnalyticsScreen()
case .reportBug:
self.presentBugReportScreen()
case .about:
self.presentLegalInformationScreen()
case .sessionVerification:
self.verifySession()
case .developerOptions:
@@ -96,6 +98,10 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {
parameters.navigationStackCoordinator?.push(coordinator)
}
private func presentLegalInformationScreen() {
parameters.navigationStackCoordinator?.push(LegalInformationScreenCoordinator())
}
private func verifySession() {
guard let sessionVerificationController = parameters.userSession.sessionVerificationController else {
fatalError("The sessionVerificationController should aways be valid at this point")
@@ -21,6 +21,7 @@ enum SettingsScreenViewModelAction {
case close
case analytics
case reportBug
case about
case sessionVerification
case developerOptions
case logout
@@ -44,6 +45,7 @@ enum SettingsScreenViewAction {
case close
case analytics
case reportBug
case about
case sessionVerification
case logout
case changedTimelineStyle
@@ -81,6 +81,8 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
callback?(.analytics)
case .reportBug:
callback?(.reportBug)
case .about:
callback?(.about)
case .logout:
callback?(.logout)
case .sessionVerification:
@@ -122,10 +122,17 @@ struct SettingsScreen: View {
// Report Bug
Button { context.send(viewAction: .reportBug) } label: {
Label(L10n.actionReportBug, systemImage: "questionmark.circle")
Label(L10n.actionReportBug, systemImage: "ladybug")
}
.buttonStyle(.compoundForm(accessory: .navigationLink))
.accessibilityIdentifier("reportBugButton")
// About
Button { context.send(viewAction: .about) } label: {
Label(L10n.commonAbout, systemImage: "questionmark.circle")
}
.buttonStyle(.compoundForm(accessory: .navigationLink))
.accessibilityIdentifier("aboutButton")
}
.compoundFormSection()
}
@@ -102,18 +102,14 @@ class SlidingSyncListProxy: SlidingSyncListOnceBuilt {
}
func updateVisibleRange(_ range: Range<Int>?, timelineLimit: UInt?) {
do {
if let range {
MXLog.info("Setting '\(name)' list range to \(range)")
try slidingSyncList?.setSyncMode(builder: .init().addRange(start: UInt32(range.lowerBound), endInclusive: UInt32(range.upperBound)))
}
if let timelineLimit {
MXLog.info("Setting '\(name)' list timeline limit to \(timelineLimit)")
slidingSyncList?.setTimelineLimit(value: UInt32(timelineLimit))
}
} catch {
MXLog.error("Failed setting sliding sync list range with error: \(error)")
if let range {
MXLog.info("Setting '\(name)' list range to \(range)")
slidingSyncList?.setSyncMode(builder: .init().addRange(start: UInt32(range.lowerBound), endInclusive: UInt32(range.upperBound)))
}
if let timelineLimit {
MXLog.info("Setting '\(name)' list timeline limit to \(timelineLimit)")
slidingSyncList?.setTimelineLimit(value: UInt32(timelineLimit))
}
}